aboutsummaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kbuild2
-rw-r--r--arch/mips/Kbuild.platforms2
-rw-r--r--arch/mips/Kconfig538
-rw-r--r--arch/mips/Kconfig.debug21
-rw-r--r--arch/mips/Makefile31
-rw-r--r--arch/mips/alchemy/Kconfig24
-rw-r--r--arch/mips/alchemy/Platform16
-rw-r--r--arch/mips/alchemy/board-gpr.c4
-rw-r--r--arch/mips/alchemy/board-mtx1.c6
-rw-r--r--arch/mips/alchemy/board-xxs1500.c2
-rw-r--r--arch/mips/alchemy/common/power.c1
-rw-r--r--arch/mips/alchemy/common/setup.c16
-rw-r--r--arch/mips/alchemy/common/sleeper.S6
-rw-r--r--arch/mips/alchemy/common/usb.c27
-rw-r--r--arch/mips/alchemy/devboards/Makefile4
-rw-r--r--arch/mips/alchemy/devboards/db1000.c54
-rw-r--r--arch/mips/alchemy/devboards/db1200.c78
-rw-r--r--arch/mips/alchemy/devboards/db1300.c40
-rw-r--r--arch/mips/alchemy/devboards/db1550.c10
-rw-r--r--arch/mips/alchemy/devboards/db1xxx.c (renamed from arch/mips/alchemy/devboards/db1235.c)43
-rw-r--r--arch/mips/alchemy/devboards/pm.c4
-rw-r--r--arch/mips/ar7/setup.c1
-rw-r--r--arch/mips/ath79/Kconfig8
-rw-r--r--arch/mips/ath79/common.h1
-rw-r--r--arch/mips/ath79/dev-common.c6
-rw-r--r--arch/mips/bcm47xx/Kconfig4
-rw-r--r--arch/mips/bcm47xx/Makefile2
-rw-r--r--arch/mips/bcm47xx/bcm47xx_private.h15
-rw-r--r--arch/mips/bcm47xx/board.c335
-rw-r--r--arch/mips/bcm47xx/buttons.c562
-rw-r--r--arch/mips/bcm47xx/irq.c25
-rw-r--r--arch/mips/bcm47xx/leds.c591
-rw-r--r--arch/mips/bcm47xx/nvram.c23
-rw-r--r--arch/mips/bcm47xx/prom.c127
-rw-r--r--arch/mips/bcm47xx/serial.c6
-rw-r--r--arch/mips/bcm47xx/setup.c50
-rw-r--r--arch/mips/bcm47xx/sprom.c19
-rw-r--r--arch/mips/bcm47xx/time.c23
-rw-r--r--arch/mips/bcm47xx/wgt634u.c174
-rw-r--r--arch/mips/bcm47xx/workarounds.c31
-rw-r--r--arch/mips/bcm63xx/Kconfig8
-rw-r--r--arch/mips/bcm63xx/Makefile4
-rw-r--r--arch/mips/bcm63xx/boards/board_bcm963xx.c3
-rw-r--r--arch/mips/bcm63xx/clk.c42
-rw-r--r--arch/mips/bcm63xx/cpu.c13
-rw-r--r--arch/mips/bcm63xx/dev-hsspi.c47
-rw-r--r--arch/mips/bcm63xx/early_printk.c3
-rw-r--r--arch/mips/bcm63xx/prom.c14
-rw-r--r--arch/mips/boot/compressed/Makefile10
-rw-r--r--arch/mips/boot/compressed/dbg.c1
-rw-r--r--arch/mips/boot/compressed/decompress.c27
-rw-r--r--arch/mips/boot/compressed/ld.script5
-rw-r--r--arch/mips/boot/compressed/string.c28
-rw-r--r--arch/mips/boot/compressed/uart-16550.c5
l---------arch/mips/boot/dts/include/dt-bindings2
-rw-r--r--arch/mips/boot/ecoff.h1
-rw-r--r--arch/mips/cavium-octeon/Kconfig23
-rw-r--r--arch/mips/cavium-octeon/csrc-octeon.c1
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c1
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-board.c27
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-util.c4
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper.c176
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-pko.c3
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-spi.c1
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c26
-rw-r--r--arch/mips/cavium-octeon/octeon-platform.c38
-rw-r--r--arch/mips/cavium-octeon/octeon_3xxx.dts19
-rw-r--r--arch/mips/cavium-octeon/setup.c39
-rw-r--r--arch/mips/cavium-octeon/smp.c26
-rw-r--r--arch/mips/cobalt/Makefile1
-rw-r--r--arch/mips/cobalt/console.c20
-rw-r--r--arch/mips/cobalt/setup.c3
-rw-r--r--arch/mips/configs/ar7_defconfig1
-rw-r--r--arch/mips/configs/ath79_defconfig3
-rw-r--r--arch/mips/configs/bcm47xx_defconfig623
-rw-r--r--arch/mips/configs/bcm63xx_defconfig1
-rw-r--r--arch/mips/configs/cobalt_defconfig1
-rw-r--r--arch/mips/configs/db1000_defconfig359
-rw-r--r--arch/mips/configs/db1235_defconfig435
-rw-r--r--arch/mips/configs/db1xxx_defconfig246
-rw-r--r--arch/mips/configs/fuloong2e_defconfig1
-rw-r--r--arch/mips/configs/gpr_defconfig1
-rw-r--r--arch/mips/configs/jmr3927_defconfig1
-rw-r--r--arch/mips/configs/lasat_defconfig1
-rw-r--r--arch/mips/configs/lemote2f_defconfig1
-rw-r--r--arch/mips/configs/loongson3_defconfig362
-rw-r--r--arch/mips/configs/malta_defconfig9
-rw-r--r--arch/mips/configs/malta_kvm_defconfig10
-rw-r--r--arch/mips/configs/malta_kvm_guest_defconfig7
-rw-r--r--arch/mips/configs/maltaaprp_defconfig3
-rw-r--r--arch/mips/configs/maltasmvp_defconfig7
-rw-r--r--arch/mips/configs/maltasmvp_eva_defconfig (renamed from arch/mips/configs/maltasmtc_defconfig)19
-rw-r--r--arch/mips/configs/maltaup_defconfig3
-rw-r--r--arch/mips/configs/markeins_defconfig1
-rw-r--r--arch/mips/configs/mips_paravirt_defconfig103
-rw-r--r--arch/mips/configs/mpc30x_defconfig1
-rw-r--r--arch/mips/configs/msp71xx_defconfig1
-rw-r--r--arch/mips/configs/mtx1_defconfig2
-rw-r--r--arch/mips/configs/pnx8335_stb225_defconfig1
-rw-r--r--arch/mips/configs/powertv_defconfig136
-rw-r--r--arch/mips/configs/qi_lb60_defconfig188
-rw-r--r--arch/mips/configs/rb532_defconfig1
-rw-r--r--arch/mips/configs/rbtx49xx_defconfig1
-rw-r--r--arch/mips/configs/rm200_defconfig1
-rw-r--r--arch/mips/configs/rt305x_defconfig2
-rw-r--r--arch/mips/configs/sb1250_swarm_defconfig1
-rw-r--r--arch/mips/configs/tb0219_defconfig1
-rw-r--r--arch/mips/configs/tb0226_defconfig1
-rw-r--r--arch/mips/dec/Makefile2
-rw-r--r--arch/mips/dec/ecc-berr.c1
-rw-r--r--arch/mips/dec/int-handler.S8
-rw-r--r--arch/mips/dec/ioasic-irq.c43
-rw-r--r--arch/mips/dec/kn02xa-berr.c1
-rw-r--r--arch/mips/dec/platform.c44
-rw-r--r--arch/mips/dec/prom/Makefile1
-rw-r--r--arch/mips/dec/prom/call_o32.S89
-rw-r--r--arch/mips/dec/prom/init.c3
-rw-r--r--arch/mips/dec/prom/memory.c2
-rw-r--r--arch/mips/dec/setup.c9
-rw-r--r--arch/mips/emma/markeins/setup.c3
-rw-r--r--arch/mips/fw/arc/file.c1
-rw-r--r--arch/mips/fw/lib/call_o32.S57
-rw-r--r--arch/mips/fw/sni/sniprom.c3
-rw-r--r--arch/mips/include/asm/Kbuild3
-rw-r--r--arch/mips/include/asm/addrspace.h4
-rw-r--r--arch/mips/include/asm/amon.h15
-rw-r--r--arch/mips/include/asm/asm-eva.h135
-rw-r--r--arch/mips/include/asm/asm.h13
-rw-r--r--arch/mips/include/asm/asmmacro-32.h170
-rw-r--r--arch/mips/include/asm/asmmacro-64.h96
-rw-r--r--arch/mips/include/asm/asmmacro.h366
-rw-r--r--arch/mips/include/asm/atomic.h51
-rw-r--r--arch/mips/include/asm/barrier.h24
-rw-r--r--arch/mips/include/asm/bitops.h39
-rw-r--r--arch/mips/include/asm/bmips.h29
-rw-r--r--arch/mips/include/asm/bootinfo.h26
-rw-r--r--arch/mips/include/asm/branch.h30
-rw-r--r--arch/mips/include/asm/cacheflush.h6
-rw-r--r--arch/mips/include/asm/cacheops.h93
-rw-r--r--arch/mips/include/asm/checksum.h44
-rw-r--r--arch/mips/include/asm/clkdev.h2
-rw-r--r--arch/mips/include/asm/cmp.h1
-rw-r--r--arch/mips/include/asm/cmpxchg.h20
-rw-r--r--arch/mips/include/asm/cpu-features.h43
-rw-r--r--arch/mips/include/asm/cpu-info.h47
-rw-r--r--arch/mips/include/asm/cpu-type.h216
-rw-r--r--arch/mips/include/asm/cpu.h66
-rw-r--r--arch/mips/include/asm/dec/ioasic.h2
-rw-r--r--arch/mips/include/asm/dec/ioasic_addrs.h2
-rw-r--r--arch/mips/include/asm/dec/kn01.h12
-rw-r--r--arch/mips/include/asm/dec/kn02ca.h2
-rw-r--r--arch/mips/include/asm/dec/kn05.h15
-rw-r--r--arch/mips/include/asm/dec/prom.h50
-rw-r--r--arch/mips/include/asm/dma-coherence.h9
-rw-r--r--arch/mips/include/asm/dma-mapping.h5
-rw-r--r--arch/mips/include/asm/elf.h32
-rw-r--r--arch/mips/include/asm/fixmap.h37
-rw-r--r--arch/mips/include/asm/fpu.h115
-rw-r--r--arch/mips/include/asm/fpu_emulator.h21
-rw-r--r--arch/mips/include/asm/ftrace.h20
-rw-r--r--arch/mips/include/asm/futex.h25
-rw-r--r--arch/mips/include/asm/fw/fw.h2
-rw-r--r--arch/mips/include/asm/gcmpregs.h125
-rw-r--r--arch/mips/include/asm/gic.h4
-rw-r--r--arch/mips/include/asm/gio_device.h4
-rw-r--r--arch/mips/include/asm/highmem.h1
-rw-r--r--arch/mips/include/asm/idle.h14
-rw-r--r--arch/mips/include/asm/io.h8
-rw-r--r--arch/mips/include/asm/irq.h96
-rw-r--r--arch/mips/include/asm/irqflags.h32
-rw-r--r--arch/mips/include/asm/jump_label.h2
-rw-r--r--arch/mips/include/asm/kvm_host.h602
-rw-r--r--arch/mips/include/asm/kvm_para.h109
-rw-r--r--arch/mips/include/asm/local.h8
-rw-r--r--arch/mips/include/asm/mach-ath79/ar71xx_regs.h1
-rw-r--r--arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h18
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1000.h16
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx.h2
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h117
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h2
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h82
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h18
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h8
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h120
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h1
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h12
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/irq.h2
-rw-r--r--arch/mips/include/asm/mach-db1x00/db1200.h91
-rw-r--r--arch/mips/include/asm/mach-db1x00/db1300.h40
-rw-r--r--arch/mips/include/asm/mach-dec/cpu-feature-overrides.h87
-rw-r--r--arch/mips/include/asm/mach-generic/dma-coherence.h14
-rw-r--r--arch/mips/include/asm/mach-generic/floppy.h1
-rw-r--r--arch/mips/include/asm/mach-generic/ide.h6
-rw-r--r--arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h6
-rw-r--r--arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h2
-rw-r--r--arch/mips/include/asm/mach-ip27/dma-coherence.h10
-rw-r--r--arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h2
-rw-r--r--arch/mips/include/asm/mach-ip32/dma-coherence.h11
-rw-r--r--arch/mips/include/asm/mach-jazz/dma-coherence.h10
-rw-r--r--arch/mips/include/asm/mach-jazz/floppy.h1
-rw-r--r--arch/mips/include/asm/mach-jz4740/dma.h2
-rw-r--r--arch/mips/include/asm/mach-jz4740/platform.h1
-rw-r--r--arch/mips/include/asm/mach-loongson/boot_param.h163
-rw-r--r--arch/mips/include/asm/mach-loongson/dma-coherence.h32
-rw-r--r--arch/mips/include/asm/mach-loongson/irq.h44
-rw-r--r--arch/mips/include/asm/mach-loongson/loongson.h28
-rw-r--r--arch/mips/include/asm/mach-loongson/machine.h6
-rw-r--r--arch/mips/include/asm/mach-loongson/pci.h5
-rw-r--r--arch/mips/include/asm/mach-loongson/spaces.h9
-rw-r--r--arch/mips/include/asm/mach-malta/kernel-entry-init.h103
-rw-r--r--arch/mips/include/asm/mach-malta/malta-pm.h37
-rw-r--r--arch/mips/include/asm/mach-malta/spaces.h46
-rw-r--r--arch/mips/include/asm/mach-netlogic/irq.h3
-rw-r--r--arch/mips/include/asm/mach-netlogic/multi-node.h33
-rw-r--r--arch/mips/include/asm/mach-netlogic/topology.h22
-rw-r--r--arch/mips/include/asm/mach-paravirt/cpu-feature-overrides.h36
-rw-r--r--arch/mips/include/asm/mach-paravirt/irq.h19
-rw-r--r--arch/mips/include/asm/mach-paravirt/kernel-entry-init.h50
-rw-r--r--arch/mips/include/asm/mach-paravirt/war.h (renamed from arch/mips/include/asm/mach-powertv/war.h)16
-rw-r--r--arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h12
-rw-r--r--arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h4
-rw-r--r--arch/mips/include/asm/mach-powertv/asic.h120
-rw-r--r--arch/mips/include/asm/mach-powertv/asic_reg_map.h90
-rw-r--r--arch/mips/include/asm/mach-powertv/asic_regs.h125
-rw-r--r--arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h60
-rw-r--r--arch/mips/include/asm/mach-powertv/dma-coherence.h117
-rw-r--r--arch/mips/include/asm/mach-powertv/interrupts.h253
-rw-r--r--arch/mips/include/asm/mach-powertv/ioremap.h167
-rw-r--r--arch/mips/include/asm/mach-powertv/irq.h25
-rw-r--r--arch/mips/include/asm/mach-powertv/powertv-clock.h29
-rw-r--r--arch/mips/include/asm/mach-ralink/war.h1
-rw-r--r--arch/mips/include/asm/mach-sead3/kernel-entry-init.h31
-rw-r--r--arch/mips/include/asm/mips-boards/generic.h4
-rw-r--r--arch/mips/include/asm/mips-boards/malta.h5
-rw-r--r--arch/mips/include/asm/mips-boards/piix4.h94
-rw-r--r--arch/mips/include/asm/mips-cm.h322
-rw-r--r--arch/mips/include/asm/mips-cpc.h182
-rw-r--r--arch/mips/include/asm/mips_mt.h10
-rw-r--r--arch/mips/include/asm/mipsmtregs.h13
-rw-r--r--arch/mips/include/asm/mipsregs.h265
-rw-r--r--arch/mips/include/asm/mmu_context.h134
-rw-r--r--arch/mips/include/asm/module.h10
-rw-r--r--arch/mips/include/asm/msa.h212
-rw-r--r--arch/mips/include/asm/netlogic/common.h24
-rw-r--r--arch/mips/include/asm/netlogic/mips-extns.h8
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/bridge.h69
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/iomap.h62
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/pcibus.h55
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/pic.h81
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/sys.h53
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/uart.h3
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/xlp.h48
-rw-r--r--arch/mips/include/asm/netlogic/xlr/xlr.h5
-rw-r--r--arch/mips/include/asm/nile4.h2
-rw-r--r--arch/mips/include/asm/octeon/cvmx-helper-board.h9
-rw-r--r--arch/mips/include/asm/octeon/cvmx-pip.h4
-rw-r--r--arch/mips/include/asm/octeon/octeon.h1
-rw-r--r--arch/mips/include/asm/page.h27
-rw-r--r--arch/mips/include/asm/pci.h17
-rw-r--r--arch/mips/include/asm/pgalloc.h9
-rw-r--r--arch/mips/include/asm/pgtable-bits.h9
-rw-r--r--arch/mips/include/asm/pgtable.h2
-rw-r--r--arch/mips/include/asm/pm-cps.h51
-rw-r--r--arch/mips/include/asm/pm.h159
-rw-r--r--arch/mips/include/asm/processor.h45
-rw-r--r--arch/mips/include/asm/prom.h20
-rw-r--r--arch/mips/include/asm/ptrace.h19
-rw-r--r--arch/mips/include/asm/r4kcache.h264
-rw-r--r--arch/mips/include/asm/rm9k-ocd.h56
-rw-r--r--arch/mips/include/asm/rtlx.h49
-rw-r--r--arch/mips/include/asm/setup.h8
-rw-r--r--arch/mips/include/asm/sgi/ip22.h2
-rw-r--r--arch/mips/include/asm/smp-cps.h44
-rw-r--r--arch/mips/include/asm/smp-ops.h18
-rw-r--r--arch/mips/include/asm/smp.h4
-rw-r--r--arch/mips/include/asm/smtc.h78
-rw-r--r--arch/mips/include/asm/smtc_ipi.h129
-rw-r--r--arch/mips/include/asm/smtc_proc.h23
-rw-r--r--arch/mips/include/asm/stackframe.h222
-rw-r--r--arch/mips/include/asm/switch_to.h34
-rw-r--r--arch/mips/include/asm/syscall.h145
-rw-r--r--arch/mips/include/asm/thread_info.h44
-rw-r--r--arch/mips/include/asm/time.h7
-rw-r--r--arch/mips/include/asm/timex.h62
-rw-r--r--arch/mips/include/asm/tlb.h4
-rw-r--r--arch/mips/include/asm/topology.h4
-rw-r--r--arch/mips/include/asm/uaccess.h559
-rw-r--r--arch/mips/include/asm/uasm.h27
-rw-r--r--arch/mips/include/asm/unistd.h9
-rw-r--r--arch/mips/include/asm/vga.h3
-rw-r--r--arch/mips/include/asm/vpe.h133
-rw-r--r--arch/mips/include/uapi/asm/Kbuild1
-rw-r--r--arch/mips/include/uapi/asm/bitfield.h29
-rw-r--r--arch/mips/include/uapi/asm/errno.h2
-rw-r--r--arch/mips/include/uapi/asm/inst.h465
-rw-r--r--arch/mips/include/uapi/asm/kvm.h35
-rw-r--r--arch/mips/include/uapi/asm/kvm_para.h6
-rw-r--r--arch/mips/include/uapi/asm/siginfo.h9
-rw-r--r--arch/mips/include/uapi/asm/socket.h4
-rw-r--r--arch/mips/include/uapi/asm/types.h5
-rw-r--r--arch/mips/include/uapi/asm/unistd.h21
-rw-r--r--arch/mips/jz4740/board-qi_lb60.c12
-rw-r--r--arch/mips/jz4740/platform.c41
-rw-r--r--arch/mips/kernel/Makefile20
-rw-r--r--arch/mips/kernel/asm-offsets.c101
-rw-r--r--arch/mips/kernel/binfmt_elfo32.c14
-rw-r--r--arch/mips/kernel/bmips_vec.S58
-rw-r--r--arch/mips/kernel/branch.c210
-rw-r--r--arch/mips/kernel/cevt-gic.c5
-rw-r--r--arch/mips/kernel/cevt-r4k.c24
-rw-r--r--arch/mips/kernel/cevt-smtc.c324
-rw-r--r--arch/mips/kernel/cps-vec.S487
-rw-r--r--arch/mips/kernel/cpu-probe.c278
-rw-r--r--arch/mips/kernel/crash.c1
-rw-r--r--arch/mips/kernel/csrc-powertv.c151
-rw-r--r--arch/mips/kernel/early_printk_8250.c66
-rw-r--r--arch/mips/kernel/entry.S38
-rw-r--r--arch/mips/kernel/ftrace.c47
-rw-r--r--arch/mips/kernel/genex.S77
-rw-r--r--arch/mips/kernel/head.S58
-rw-r--r--arch/mips/kernel/i8259.c4
-rw-r--r--arch/mips/kernel/idle.c39
-rw-r--r--arch/mips/kernel/irq-gic.c16
-rw-r--r--arch/mips/kernel/irq-msc01.c7
-rw-r--r--arch/mips/kernel/irq.c21
-rw-r--r--arch/mips/kernel/irq_cpu.c2
-rw-r--r--arch/mips/kernel/kgdb.c18
-rw-r--r--arch/mips/kernel/mips-cm.c121
-rw-r--r--arch/mips/kernel/mips-cpc.c80
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c2
-rw-r--r--arch/mips/kernel/mips-mt.c18
-rw-r--r--arch/mips/kernel/mips_ksyms.c24
-rw-r--r--arch/mips/kernel/module.c3
-rw-r--r--arch/mips/kernel/octeon_switch.S86
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c84
-rw-r--r--arch/mips/kernel/pm-cps.c716
-rw-r--r--arch/mips/kernel/pm.c99
-rw-r--r--arch/mips/kernel/proc.c64
-rw-r--r--arch/mips/kernel/process.c36
-rw-r--r--arch/mips/kernel/prom.c62
-rw-r--r--arch/mips/kernel/ptrace.c384
-rw-r--r--arch/mips/kernel/ptrace32.c88
-rw-r--r--arch/mips/kernel/r2300_switch.S2
-rw-r--r--arch/mips/kernel/r4k_fpu.S84
-rw-r--r--arch/mips/kernel/r4k_switch.S143
-rw-r--r--arch/mips/kernel/rtlx-cmp.c119
-rw-r--r--arch/mips/kernel/rtlx-mt.c150
-rw-r--r--arch/mips/kernel/rtlx.c288
-rw-r--r--arch/mips/kernel/scall32-o32.S865
-rw-r--r--arch/mips/kernel/scall64-64.S11
-rw-r--r--arch/mips/kernel/scall64-n32.S9
-rw-r--r--arch/mips/kernel/scall64-o32.S30
-rw-r--r--arch/mips/kernel/segment.c110
-rw-r--r--arch/mips/kernel/setup.c19
-rw-r--r--arch/mips/kernel/signal.c91
-rw-r--r--arch/mips/kernel/signal32.c65
-rw-r--r--arch/mips/kernel/smp-bmips.c323
-rw-r--r--arch/mips/kernel/smp-cmp.c73
-rw-r--r--arch/mips/kernel/smp-cps.c466
-rw-r--r--arch/mips/kernel/smp-gic.c64
-rw-r--r--arch/mips/kernel/smp-mt.c34
-rw-r--r--arch/mips/kernel/smp-up.c6
-rw-r--r--arch/mips/kernel/smp.c62
-rw-r--r--arch/mips/kernel/smtc-asm.S133
-rw-r--r--arch/mips/kernel/smtc-proc.c79
-rw-r--r--arch/mips/kernel/smtc.c1528
-rw-r--r--arch/mips/kernel/spram.c8
-rw-r--r--arch/mips/kernel/sync-r4k.c19
-rw-r--r--arch/mips/kernel/syscall.c4
-rw-r--r--arch/mips/kernel/time.c2
-rw-r--r--arch/mips/kernel/traps.c374
-rw-r--r--arch/mips/kernel/unaligned.c135
-rw-r--r--arch/mips/kernel/vpe-cmp.c180
-rw-r--r--arch/mips/kernel/vpe-mt.c521
-rw-r--r--arch/mips/kernel/vpe.c910
-rw-r--r--arch/mips/kvm/kvm_locore.S32
-rw-r--r--arch/mips/kvm/kvm_mips.c152
-rw-r--r--arch/mips/kvm/kvm_mips_dyntrans.c15
-rw-r--r--arch/mips/kvm/kvm_mips_emul.c597
-rw-r--r--arch/mips/kvm/kvm_tlb.c206
-rw-r--r--arch/mips/kvm/kvm_trap_emul.c86
-rw-r--r--arch/mips/lantiq/dts/easy50712.dts1
-rw-r--r--arch/mips/lantiq/irq.c6
-rw-r--r--arch/mips/lantiq/prom.c16
-rw-r--r--arch/mips/lantiq/prom.h2
-rw-r--r--arch/mips/lantiq/xway/clk.c1
-rw-r--r--arch/mips/lantiq/xway/dma.c4
-rw-r--r--arch/mips/lantiq/xway/sysctrl.c2
-rw-r--r--arch/mips/lasat/at93c.c1
-rw-r--r--arch/mips/lasat/picvue.c1
-rw-r--r--arch/mips/lasat/picvue_proc.c2
-rw-r--r--arch/mips/lib/csum_partial.S291
-rw-r--r--arch/mips/lib/delay.c18
-rw-r--r--arch/mips/lib/memcpy.S416
-rw-r--r--arch/mips/lib/memset.S146
-rw-r--r--arch/mips/lib/mips-atomic.c46
-rw-r--r--arch/mips/lib/strlen_user.S36
-rw-r--r--arch/mips/lib/strncpy_user.S51
-rw-r--r--arch/mips/lib/strnlen_user.S36
-rw-r--r--arch/mips/lib/uncached.c1
-rw-r--r--arch/mips/loongson/Kconfig51
-rw-r--r--arch/mips/loongson/Makefile6
-rw-r--r--arch/mips/loongson/Platform1
-rw-r--r--arch/mips/loongson/common/Makefile5
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_mfgpt.c11
-rw-r--r--arch/mips/loongson/common/dma-swiotlb.c136
-rw-r--r--arch/mips/loongson/common/env.c67
-rw-r--r--arch/mips/loongson/common/init.c11
-rw-r--r--arch/mips/loongson/common/machtype.c4
-rw-r--r--arch/mips/loongson/common/mem.c42
-rw-r--r--arch/mips/loongson/common/pci.c6
-rw-r--r--arch/mips/loongson/common/reset.c21
-rw-r--r--arch/mips/loongson/common/serial.c26
-rw-r--r--arch/mips/loongson/common/setup.c8
-rw-r--r--arch/mips/loongson/common/uart_base.c9
-rw-r--r--arch/mips/loongson/lemote-2f/clock.c37
-rw-r--r--arch/mips/loongson/loongson-3/Makefile6
-rw-r--r--arch/mips/loongson/loongson-3/irq.c126
-rw-r--r--arch/mips/loongson/loongson-3/smp.c435
-rw-r--r--arch/mips/loongson/loongson-3/smp.h29
-rw-r--r--arch/mips/loongson1/Kconfig1
-rw-r--r--arch/mips/math-emu/Makefile16
-rw-r--r--arch/mips/math-emu/cp1emu.c1016
-rw-r--r--arch/mips/math-emu/dp_add.c71
-rw-r--r--arch/mips/math-emu/dp_cmp.c24
-rw-r--r--arch/mips/math-emu/dp_div.c94
-rw-r--r--arch/mips/math-emu/dp_fint.c33
-rw-r--r--arch/mips/math-emu/dp_flong.c28
-rw-r--r--arch/mips/math-emu/dp_frexp.c52
-rw-r--r--arch/mips/math-emu/dp_fsp.c32
-rw-r--r--arch/mips/math-emu/dp_logb.c53
-rw-r--r--arch/mips/math-emu/dp_modf.c79
-rw-r--r--arch/mips/math-emu/dp_mul.c143
-rw-r--r--arch/mips/math-emu/dp_scalb.c57
-rw-r--r--arch/mips/math-emu/dp_simple.c39
-rw-r--r--arch/mips/math-emu/dp_sqrt.c46
-rw-r--r--arch/mips/math-emu/dp_sub.c55
-rw-r--r--arch/mips/math-emu/dp_tint.c69
-rw-r--r--arch/mips/math-emu/dp_tlong.c68
-rw-r--r--arch/mips/math-emu/dsemul.c35
-rw-r--r--arch/mips/math-emu/ieee754.c151
-rw-r--r--arch/mips/math-emu/ieee754.h322
-rw-r--r--arch/mips/math-emu/ieee754d.c39
-rw-r--r--arch/mips/math-emu/ieee754dp.c122
-rw-r--r--arch/mips/math-emu/ieee754dp.h70
-rw-r--r--arch/mips/math-emu/ieee754int.h201
-rw-r--r--arch/mips/math-emu/ieee754m.c55
-rw-r--r--arch/mips/math-emu/ieee754sp.c126
-rw-r--r--arch/mips/math-emu/ieee754sp.h79
-rw-r--r--arch/mips/math-emu/ieee754xcpt.c47
-rw-r--r--arch/mips/math-emu/kernel_linkage.c115
-rw-r--r--arch/mips/math-emu/me-debugfs.c67
-rw-r--r--arch/mips/math-emu/sp_add.c72
-rw-r--r--arch/mips/math-emu/sp_cmp.c24
-rw-r--r--arch/mips/math-emu/sp_div.c93
-rw-r--r--arch/mips/math-emu/sp_fdp.c56
-rw-r--r--arch/mips/math-emu/sp_fint.c30
-rw-r--r--arch/mips/math-emu/sp_flong.c30
-rw-r--r--arch/mips/math-emu/sp_frexp.c52
-rw-r--r--arch/mips/math-emu/sp_logb.c53
-rw-r--r--arch/mips/math-emu/sp_modf.c79
-rw-r--r--arch/mips/math-emu/sp_mul.c139
-rw-r--r--arch/mips/math-emu/sp_scalb.c57
-rw-r--r--arch/mips/math-emu/sp_simple.c39
-rw-r--r--arch/mips/math-emu/sp_sqrt.c35
-rw-r--r--arch/mips/math-emu/sp_sub.c57
-rw-r--r--arch/mips/math-emu/sp_tint.c67
-rw-r--r--arch/mips/math-emu/sp_tlong.c69
-rw-r--r--arch/mips/mm/c-octeon.c9
-rw-r--r--arch/mips/mm/c-r3k.c1
-rw-r--r--arch/mips/mm/c-r4k.c357
-rw-r--r--arch/mips/mm/cache.c10
-rw-r--r--arch/mips/mm/cex-sb1.S1
-rw-r--r--arch/mips/mm/dma-default.c19
-rw-r--r--arch/mips/mm/hugetlbpage.c6
-rw-r--r--arch/mips/mm/init.c99
-rw-r--r--arch/mips/mm/page.c6
-rw-r--r--arch/mips/mm/sc-mips.c7
-rw-r--r--arch/mips/mm/sc-rm7k.c1
-rw-r--r--arch/mips/mm/tlb-funcs.S6
-rw-r--r--arch/mips/mm/tlb-r3k.c1
-rw-r--r--arch/mips/mm/tlb-r4k.c177
-rw-r--r--arch/mips/mm/tlb-r8k.c1
-rw-r--r--arch/mips/mm/tlbex.c325
-rw-r--r--arch/mips/mm/uasm-micromips.c16
-rw-r--r--arch/mips/mm/uasm-mips.c17
-rw-r--r--arch/mips/mm/uasm.c59
-rw-r--r--arch/mips/mti-malta/Makefile5
-rw-r--r--arch/mips/mti-malta/malta-amon.c49
-rw-r--r--arch/mips/mti-malta/malta-console.c47
-rw-r--r--arch/mips/mti-malta/malta-init.c92
-rw-r--r--arch/mips/mti-malta/malta-int.c229
-rw-r--r--arch/mips/mti-malta/malta-memory.c58
-rw-r--r--arch/mips/mti-malta/malta-platform.c2
-rw-r--r--arch/mips/mti-malta/malta-pm.c96
-rw-r--r--arch/mips/mti-malta/malta-reset.c14
-rw-r--r--arch/mips/mti-malta/malta-setup.c34
-rw-r--r--arch/mips/mti-malta/malta-smtc.c162
-rw-r--r--arch/mips/mti-malta/malta-time.c33
-rw-r--r--arch/mips/mti-sead3/Makefile2
-rw-r--r--arch/mips/mti-sead3/sead3-mtd.c3
-rw-r--r--arch/mips/mti-sead3/sead3-pic32-bus.c1
-rw-r--r--arch/mips/mti-sead3/sead3-pic32-i2c-drv.c36
-rw-r--r--arch/mips/mti-sead3/sead3-setup.c88
-rw-r--r--arch/mips/mti-sead3/sead3-time.c7
-rw-r--r--arch/mips/mti-sead3/sead3.dts4
-rw-r--r--arch/mips/net/Makefile3
-rw-r--r--arch/mips/net/bpf_jit.c1431
-rw-r--r--arch/mips/net/bpf_jit.h44
-rw-r--r--arch/mips/netlogic/Kconfig9
-rw-r--r--arch/mips/netlogic/common/earlycons.c2
-rw-r--r--arch/mips/netlogic/common/irq.c74
-rw-r--r--arch/mips/netlogic/common/reset.S98
-rw-r--r--arch/mips/netlogic/common/smp.c20
-rw-r--r--arch/mips/netlogic/common/smpboot.S16
-rw-r--r--arch/mips/netlogic/common/time.c5
-rw-r--r--arch/mips/netlogic/dts/Makefile1
-rw-r--r--arch/mips/netlogic/dts/xlp_gvp.dts77
-rw-r--r--arch/mips/netlogic/xlp/Makefile2
-rw-r--r--arch/mips/netlogic/xlp/ahci-init-xlp2.c377
-rw-r--r--arch/mips/netlogic/xlp/ahci-init.c209
-rw-r--r--arch/mips/netlogic/xlp/dt.c37
-rw-r--r--arch/mips/netlogic/xlp/nlm_hal.c284
-rw-r--r--arch/mips/netlogic/xlp/setup.c31
-rw-r--r--arch/mips/netlogic/xlp/usb-init-xlp2.c88
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c98
-rw-r--r--arch/mips/netlogic/xlr/fmn-config.c3
-rw-r--r--arch/mips/netlogic/xlr/platform.c4
-rw-r--r--arch/mips/netlogic/xlr/setup.c21
-rw-r--r--arch/mips/netlogic/xlr/wakeup.c3
-rw-r--r--arch/mips/oprofile/common.c6
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c17
-rw-r--r--arch/mips/paravirt/Kconfig6
-rw-r--r--arch/mips/paravirt/Makefile14
-rw-r--r--arch/mips/paravirt/Platform8
-rw-r--r--arch/mips/paravirt/paravirt-irq.c368
-rw-r--r--arch/mips/paravirt/paravirt-smp.c143
-rw-r--r--arch/mips/paravirt/serial.c40
-rw-r--r--arch/mips/paravirt/setup.c67
-rw-r--r--arch/mips/pci/Makefile4
-rw-r--r--arch/mips/pci/fixup-lantiq.c13
-rw-r--r--arch/mips/pci/fixup-loongson3.c66
-rw-r--r--arch/mips/pci/fixup-malta.c66
-rw-r--r--arch/mips/pci/fixup-rc32434.c1
-rw-r--r--arch/mips/pci/fixup-sb1250.c1
-rw-r--r--arch/mips/pci/msi-octeon.c7
-rw-r--r--arch/mips/pci/msi-xlp.c572
-rw-r--r--arch/mips/pci/ops-bcm63xx.c1
-rw-r--r--arch/mips/pci/ops-bonito64.c1
-rw-r--r--arch/mips/pci/ops-lantiq.c1
-rw-r--r--arch/mips/pci/ops-loongson2.c1
-rw-r--r--arch/mips/pci/ops-loongson3.c101
-rw-r--r--arch/mips/pci/ops-mace.c1
-rw-r--r--arch/mips/pci/ops-msc.c1
-rw-r--r--arch/mips/pci/ops-nile4.c1
-rw-r--r--arch/mips/pci/ops-pmcmsp.c2
-rw-r--r--arch/mips/pci/ops-rc32434.c1
-rw-r--r--arch/mips/pci/ops-tx3927.c2
-rw-r--r--arch/mips/pci/ops-tx4927.c9
-rw-r--r--arch/mips/pci/pci-alchemy.c5
-rw-r--r--arch/mips/pci/pci-ar71xx.c3
-rw-r--r--arch/mips/pci/pci-ar724x.c9
-rw-r--r--arch/mips/pci/pci-bcm1480.c1
-rw-r--r--arch/mips/pci/pci-ip27.c1
-rw-r--r--arch/mips/pci/pci-malta.c28
-rw-r--r--arch/mips/pci/pci-rc32434.c1
-rw-r--r--arch/mips/pci/pci-rt3883.c27
-rw-r--r--arch/mips/pci/pci-virtio-guest.c131
-rw-r--r--arch/mips/pci/pci-xlp.c110
-rw-r--r--arch/mips/pci/pci-xlr.c10
-rw-r--r--arch/mips/pci/pci.c50
-rw-r--r--arch/mips/pmcs-msp71xx/Kconfig1
-rw-r--r--arch/mips/pmcs-msp71xx/Makefile1
-rw-r--r--arch/mips/pmcs-msp71xx/msp_eth.c76
-rw-r--r--arch/mips/pmcs-msp71xx/msp_irq.c16
-rw-r--r--arch/mips/pmcs-msp71xx/msp_irq_cic.c7
-rw-r--r--arch/mips/pmcs-msp71xx/msp_irq_per.c3
-rw-r--r--arch/mips/pmcs-msp71xx/msp_setup.c19
-rw-r--r--arch/mips/pmcs-msp71xx/msp_smtc.c104
-rw-r--r--arch/mips/pmcs-msp71xx/msp_usb.c90
-rw-r--r--arch/mips/pnx833x/common/platform.c73
-rw-r--r--arch/mips/power/hibernate.S1
-rw-r--r--arch/mips/powertv/Kconfig12
-rw-r--r--arch/mips/powertv/Makefile29
-rw-r--r--arch/mips/powertv/Platform7
-rw-r--r--arch/mips/powertv/asic/Makefile21
-rw-r--r--arch/mips/powertv/asic/asic-calliope.c101
-rw-r--r--arch/mips/powertv/asic/asic-cronus.c101
-rw-r--r--arch/mips/powertv/asic/asic-gaia.c96
-rw-r--r--arch/mips/powertv/asic/asic-zeus.c101
-rw-r--r--arch/mips/powertv/asic/asic_devices.c549
-rw-r--r--arch/mips/powertv/asic/asic_int.c125
-rw-r--r--arch/mips/powertv/asic/irq_asic.c115
-rw-r--r--arch/mips/powertv/asic/prealloc-calliope.c385
-rw-r--r--arch/mips/powertv/asic/prealloc-cronus.c340
-rw-r--r--arch/mips/powertv/asic/prealloc-cronuslite.c174
-rw-r--r--arch/mips/powertv/asic/prealloc-gaia.c589
-rw-r--r--arch/mips/powertv/asic/prealloc-zeus.c304
-rw-r--r--arch/mips/powertv/asic/prealloc.h70
-rw-r--r--arch/mips/powertv/init.c90
-rw-r--r--arch/mips/powertv/init.h28
-rw-r--r--arch/mips/powertv/ioremap.c136
-rw-r--r--arch/mips/powertv/memory.c353
-rw-r--r--arch/mips/powertv/pci/Makefile19
-rw-r--r--arch/mips/powertv/pci/fixup-powertv.c37
-rw-r--r--arch/mips/powertv/pci/powertv-pci.h31
-rw-r--r--arch/mips/powertv/powertv-clock.h26
-rw-r--r--arch/mips/powertv/powertv-usb.c404
-rw-r--r--arch/mips/powertv/powertv_setup.c319
-rw-r--r--arch/mips/powertv/reset.c35
-rw-r--r--arch/mips/powertv/reset.h26
-rw-r--r--arch/mips/powertv/time.c36
-rw-r--r--arch/mips/ralink/Kconfig7
-rw-r--r--arch/mips/ralink/cevt-rt3352.c2
-rw-r--r--arch/mips/ralink/clk.c2
-rw-r--r--arch/mips/ralink/dts/mt7620a_eval.dts1
-rw-r--r--arch/mips/ralink/dts/rt2880_eval.dts1
-rw-r--r--arch/mips/ralink/dts/rt3052_eval.dts1
-rw-r--r--arch/mips/ralink/dts/rt3883_eval.dts1
-rw-r--r--arch/mips/ralink/mt7620.c2
-rw-r--r--arch/mips/ralink/of.c32
-rw-r--r--arch/mips/ralink/rt305x.c2
-rw-r--r--arch/mips/ralink/timer.c4
-rw-r--r--arch/mips/sgi-ip22/ip22-gio.c42
-rw-r--r--arch/mips/sgi-ip22/ip22-int.c9
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-console.c1
-rw-r--r--arch/mips/sgi-ip27/ip27-irq-pci.c1
-rw-r--r--arch/mips/sgi-ip27/ip27-klconfig.c1
-rw-r--r--arch/mips/sgi-ip27/ip27-smp.c5
-rw-r--r--arch/mips/sgi-ip27/ip27-xtalk.c1
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c13
-rw-r--r--arch/mips/sibyte/bcm1480/setup.c3
-rw-r--r--arch/mips/sibyte/bcm1480/smp.c10
-rw-r--r--arch/mips/sibyte/sb1250/irq.c2
-rw-r--r--arch/mips/sibyte/sb1250/setup.c3
-rw-r--r--arch/mips/sibyte/sb1250/smp.c10
-rw-r--r--arch/mips/sibyte/swarm/setup.c2
-rw-r--r--arch/mips/sni/setup.c3
-rw-r--r--arch/mips/txx9/generic/setup.c4
640 files changed, 25410 insertions, 21328 deletions
diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild
index d2cfe45f332..dd295335891 100644
--- a/arch/mips/Kbuild
+++ b/arch/mips/Kbuild
@@ -16,7 +16,7 @@ obj- := $(platform-)
obj-y += kernel/
obj-y += mm/
-obj-y += math-emu/
+obj-y += net/
ifdef CONFIG_KVM
obj-y += kvm/
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index d9d81c21925..f5e18bf3275 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -18,9 +18,9 @@ platforms += loongson1
platforms += mti-malta
platforms += mti-sead3
platforms += netlogic
+platforms += paravirt
platforms += pmcs-msp71xx
platforms += pnx833x
-platforms += powertv
platforms += ralink
platforms += rb532
platforms += sgi-ip22
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f75ab4a2f24..4e238e6e661 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1,6 +1,8 @@
config MIPS
bool
default y
+ select ARCH_MIGHT_HAVE_PC_PARPORT
+ select ARCH_MIGHT_HAVE_PC_SERIO
select HAVE_CONTEXT_TRACKING
select HAVE_GENERIC_DMA_COHERENT
select HAVE_IDE
@@ -8,6 +10,9 @@ config MIPS
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
select HAVE_ARCH_KGDB
+ 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_FUNCTION_TRACE_MCOUNT_TEST
@@ -18,6 +23,7 @@ config MIPS
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_DEBUG_KMEMLEAK
+ select HAVE_SYSCALL_TRACEPOINTS
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
select RTC_LIB if !MACH_LOONGSON
@@ -44,6 +50,9 @@ config MIPS
select MODULES_USE_ELF_RELA if MODULES && 64BIT
select CLONE_BACKWARDS
select HAVE_DEBUG_STACKOVERFLOW
+ select HAVE_CC_STACKPROTECTOR
+ select CPU_PM if CPU_IDLE
+ select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
menu "Machine selection"
@@ -57,13 +66,12 @@ config MIPS_ALCHEMY
select CEVT_R4K
select CSRC_R4K
select IRQ_CPU
+ select DMA_MAYBE_COHERENT # Au1000,1500,1100 aren't, rest is
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_APM_EMULATION
select ARCH_REQUIRE_GPIOLIB
select SYS_SUPPORTS_ZBOOT
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
config AR7
bool "Texas Instruments AR7"
@@ -78,6 +86,7 @@ config AR7
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_MIPS16
select SYS_SUPPORTS_ZBOOT_UART16550
select ARCH_REQUIRE_GPIOLIB
select VLYNQ
@@ -101,6 +110,7 @@ config ATH79
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_MIPS16
help
Support for the Atheros AR71XX/AR724X/AR913X SoCs.
@@ -111,14 +121,15 @@ config BCM47XX
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select FW_CFE
select HW_HAS_PCI
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
select NO_EXCEPT_FILL
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_MIPS16
select SYS_HAS_EARLY_PRINTK
+ select USE_GENERIC_EARLY_PRINTK_8250
help
Support for BCM47XX based boards
@@ -129,14 +140,13 @@ config BCM63XX
select CSRC_R4K
select DMA_NONCOHERENT
select IRQ_CPU
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_HAS_EARLY_PRINTK
select SWAP_IO_SPACE
select ARCH_REQUIRE_GPIOLIB
select HAVE_CLK
+ select MIPS_L1_CACHE_SHIFT_4
help
Support for BCM63XX based boards
@@ -158,19 +168,20 @@ config MIPS_COBALT
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
+ select USE_GENERIC_EARLY_PRINTK_8250
config MACH_DECSTATION
bool "DECstations"
select BOOT_ELF32
select CEVT_DS1287
- select CEVT_R4K
+ select CEVT_R4K if CPU_R4X00
select CSRC_IOASIC
- select CSRC_R4K
+ select CSRC_R4K if CPU_R4X00
select CPU_DADDI_WORKAROUNDS if 64BIT
select CPU_R4000_WORKAROUNDS if 64BIT
select CPU_R4400_WORKAROUNDS if 64BIT
select DMA_NONCOHERENT
- select NO_IOPORT
+ select NO_IOPORT_MAP
select IRQ_CPU
select SYS_HAS_CPU_R3000
select SYS_HAS_CPU_R4X00
@@ -180,6 +191,7 @@ config MACH_DECSTATION
select SYS_SUPPORTS_128HZ
select SYS_SUPPORTS_256HZ
select SYS_SUPPORTS_1024HZ
+ select MIPS_L1_CACHE_SHIFT_4
help
This enables support for DEC's MIPS based workstations. For details
see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
@@ -229,7 +241,6 @@ config MACH_JZ4740
select IRQ_CPU
select ARCH_REQUIRE_GPIOLIB
select SYS_HAS_EARLY_PRINTK
- select HAVE_PWM
select HAVE_CLK
select GENERIC_IRQ_CHIP
@@ -243,6 +254,7 @@ config LANTIQ
select SYS_HAS_CPU_MIPS32_R2
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_MIPS16
select SYS_SUPPORTS_MULTITHREADING
select SYS_HAS_EARLY_PRINTK
select ARCH_REQUIRE_GPIOLIB
@@ -257,6 +269,7 @@ config LANTIQ
config LASAT
bool "LASAT Networks platforms"
select CEVT_R4K
+ select CRC32
select CSRC_R4K
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
@@ -299,7 +312,7 @@ config MIPS_MALTA
select CEVT_R4K
select CSRC_R4K
select CSRC_GIC
- select DMA_NONCOHERENT
+ select DMA_MAYBE_COHERENT
select GENERIC_ISA_DMA
select HAVE_PCSPKR_PLATFORM
select IRQ_CPU
@@ -314,16 +327,18 @@ config MIPS_MALTA
select SWAP_IO_SPACE
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
+ select SYS_HAS_CPU_MIPS32_R3_5
select SYS_HAS_CPU_MIPS64_R1
select SYS_HAS_CPU_MIPS64_R2
select SYS_HAS_CPU_NEVADA
select SYS_HAS_CPU_RM7000
- select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_MIPS_CMP
+ select SYS_SUPPORTS_MIPS_CPS
+ select SYS_SUPPORTS_MIPS16
select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_SMARTMIPS
select SYS_SUPPORTS_ZBOOT
@@ -343,6 +358,7 @@ config MIPS_SEAD3
select DMA_NONCOHERENT
select IRQ_CPU
select IRQ_GIC
+ select LIBFDT
select MIPS_MSC
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
@@ -354,7 +370,7 @@ config MIPS_SEAD3
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_SMARTMIPS
select SYS_SUPPORTS_MICROMIPS
- select USB_ARCH_HAS_EHCI
+ select SYS_SUPPORTS_MIPS16
select USB_EHCI_BIG_ENDIAN_DESC
select USB_EHCI_BIG_ENDIAN_MMIO
select USE_OF
@@ -374,6 +390,7 @@ config MACH_VR41XX
select CEVT_R4K
select CSRC_R4K
select SYS_HAS_CPU_VR41XX
+ select SYS_SUPPORTS_MIPS16
select ARCH_REQUIRE_GPIOLIB
config NXP_STB220
@@ -401,6 +418,7 @@ config PMC_MSP
select SYS_HAS_CPU_MIPS32_R2
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_MIPS16
select IRQ_CPU
select SERIAL_8250
select SERIAL_8250_CONSOLE
@@ -412,23 +430,6 @@ config PMC_MSP
of integrated peripherals, interfaces and DSPs in addition to
a variety of MIPS cores.
-config POWERTV
- bool "Cisco PowerTV"
- select BOOT_ELF32
- select CEVT_R4K
- select CPU_MIPSR2_IRQ_VI
- select CPU_MIPSR2_IRQ_EI
- select CSRC_POWERTV
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select SYS_HAS_CPU_MIPS32_R2
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_HIGHMEM
- select USB_OHCI_LITTLE_ENDIAN
- help
- This enables support for the Cisco PowerTV Platform.
-
config RALINK
bool "Ralink based machines"
select CEVT_R4K
@@ -441,6 +442,7 @@ config RALINK
select SYS_HAS_CPU_MIPS32_R2
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_MIPS16
select SYS_HAS_EARLY_PRINTK
select HAVE_MACH_CLKDEV
select CLKDEV_LOOKUP
@@ -482,6 +484,7 @@ config SGI_IP22
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
+ select MIPS_L1_CACHE_SHIFT_7
help
This are the SGI Indy, Challenge S and Indigo2, as well as certain
OEM variants like the Tandem CMN B006S. To compile a Linux kernel
@@ -502,6 +505,7 @@ config SGI_IP27
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_NUMA
select SYS_SUPPORTS_SMP
+ select MIPS_L1_CACHE_SHIFT_7
help
This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
workstations. To compile a Linux kernel that runs on these, say Y
@@ -708,6 +712,7 @@ config MIKROTIK_RB532
select SWAP_IO_SPACE
select BOOT_RAW
select ARCH_REQUIRE_GPIOLIB
+ select MIPS_L1_CACHE_SHIFT_4
help
Support the Mikrotik(tm) RouterBoard 532 series,
based on the IDT RC32434 SoC.
@@ -726,10 +731,13 @@ config CAVIUM_OCTEON_SOC
select SWAP_IO_SPACE
select HW_HAS_PCI
select ZONE_DMA32
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
select HOLES_IN_ZONE
select ARCH_REQUIRE_GPIOLIB
+ select LIBFDT
+ select USE_OF
+ select ARCH_SPARSEMEM_ENABLE
+ select SYS_SUPPORTS_SMP
+ select NR_CPUS_DEFAULT_16
help
This option supports all of the Octeon reference boards from Cavium
Networks. It builds a kernel that dynamically determines the Octeon
@@ -764,8 +772,6 @@ config NLM_XLR_BOARD
select ZONE_DMA32 if 64BIT
select SYNC_R4K
select SYS_HAS_EARLY_PRINTK
- select USB_ARCH_HAS_OHCI if USB_SUPPORT
- select USB_ARCH_HAS_EHCI if USB_SUPPORT
select SYS_SUPPORTS_ZBOOT
select SYS_SUPPORTS_ZBOOT_UART16550
help
@@ -800,6 +806,25 @@ config NLM_XLP_BOARD
This board is based on Netlogic XLP Processor.
Say Y here if you have a XLP based board.
+config MIPS_PARAVIRT
+ bool "Para-Virtualized guest system"
+ select CEVT_R4K
+ select CSRC_R4K
+ select DMA_COHERENT
+ select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_SMP
+ select NR_CPUS_DEFAULT_4
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_HAS_CPU_MIPS64_R2
+ select SYS_HAS_CPU_CAVIUM_OCTEON
+ select HW_HAS_PCI
+ select SWAP_IO_SPACE
+ help
+ This option supports guest running under ????
+
endchoice
source "arch/mips/alchemy/Kconfig"
@@ -811,7 +836,6 @@ source "arch/mips/jz4740/Kconfig"
source "arch/mips/lantiq/Kconfig"
source "arch/mips/lasat/Kconfig"
source "arch/mips/pmcs-msp71xx/Kconfig"
-source "arch/mips/powertv/Kconfig"
source "arch/mips/ralink/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
@@ -821,6 +845,7 @@ source "arch/mips/cavium-octeon/Kconfig"
source "arch/mips/loongson/Kconfig"
source "arch/mips/loongson1/Kconfig"
source "arch/mips/netlogic/Kconfig"
+source "arch/mips/paravirt/Kconfig"
endmenu
@@ -876,6 +901,7 @@ config CEVT_R4K
bool
config CEVT_GIC
+ select MIPS_CM
bool
config CEVT_SB1250
@@ -890,13 +916,11 @@ config CSRC_BCM1480
config CSRC_IOASIC
bool
-config CSRC_POWERTV
- bool
-
config CSRC_R4K
bool
config CSRC_GIC
+ select MIPS_CM
bool
config CSRC_SB1250
@@ -912,6 +936,10 @@ config FW_CFE
config ARCH_DMA_ADDR_T_64BIT
def_bool (HIGHMEM && 64BIT_PHYS_ADDR) || 64BIT
+config DMA_MAYBE_COHERENT
+ select DMA_NONCOHERENT
+ bool
+
config DMA_COHERENT
bool
@@ -956,7 +984,7 @@ config SYNC_R4K
config MIPS_MACHINE
def_bool n
-config NO_IOPORT
+config NO_IOPORT_MAP
def_bool n
config GENERIC_ISA_DMA
@@ -1037,6 +1065,7 @@ config IRQ_GT641XX
bool
config IRQ_GIC
+ select MIPS_CM
bool
config PCI_GT64XXX_PCI0
@@ -1067,6 +1096,7 @@ config SOC_PNX833X
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_MIPS16
select CPU_MIPSR2_IRQ_VI
config SOC_PNX8335
@@ -1106,11 +1136,24 @@ config FW_SNIPROM
config BOOT_ELF32
bool
+config MIPS_L1_CACHE_SHIFT_4
+ bool
+
+config MIPS_L1_CACHE_SHIFT_5
+ bool
+
+config MIPS_L1_CACHE_SHIFT_6
+ bool
+
+config MIPS_L1_CACHE_SHIFT_7
+ bool
+
config MIPS_L1_CACHE_SHIFT
int
- default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X
- default "6" if MIPS_CPU_SCACHE
- default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
+ default "4" if MIPS_L1_CACHE_SHIFT_4
+ default "5" if MIPS_L1_CACHE_SHIFT_5
+ default "6" if MIPS_L1_CACHE_SHIFT_6
+ default "7" if MIPS_L1_CACHE_SHIFT_7
default "5"
config HAVE_STD_PC_SERIAL_PORT
@@ -1142,6 +1185,18 @@ choice
prompt "CPU type"
default CPU_R4X00
+config CPU_LOONGSON3
+ bool "Loongson 3 CPU"
+ depends on SYS_HAS_CPU_LOONGSON3
+ select CPU_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_HIGHMEM
+ select CPU_SUPPORTS_HUGEPAGES
+ select WEAK_ORDERING
+ select WEAK_REORDERING_BEYOND_LLSC
+ help
+ The Loongson 3 processor implements the MIPS64R2 instruction
+ set with many extensions.
+
config CPU_LOONGSON2E
bool "Loongson 2E"
depends on SYS_HAS_CPU_LOONGSON2E
@@ -1197,6 +1252,7 @@ config CPU_MIPS32_R2
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
+ select CPU_SUPPORTS_MSA
select HAVE_KVM
help
Choose this option to build a kernel for release 2 or later of the
@@ -1232,6 +1288,7 @@ config CPU_MIPS64_R2
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES
+ select CPU_SUPPORTS_MSA
help
Choose this option to build a kernel for release 2 or later of the
MIPS64 architecture. Many modern embedded systems with a 64-bit
@@ -1379,58 +1436,36 @@ config CPU_SB1
config CPU_CAVIUM_OCTEON
bool "Cavium Octeon processor"
depends on SYS_HAS_CPU_CAVIUM_OCTEON
- select ARCH_SPARSEMEM_ENABLE
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_SMP
- select NR_CPUS_DEFAULT_16
select WEAK_ORDERING
select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES
- select LIBFDT
- select USE_OF
select USB_EHCI_BIG_ENDIAN_MMIO
+ select MIPS_L1_CACHE_SHIFT_7
help
The Cavium Octeon processor is a highly integrated chip containing
many ethernet hardware widgets for networking tasks. The processor
can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets.
Full details can be found at http://www.caviumnetworks.com.
-config CPU_BMIPS3300
- bool "BMIPS3300"
- depends on SYS_HAS_CPU_BMIPS3300
- select CPU_BMIPS
- help
- Broadcom BMIPS3300 processors.
-
-config CPU_BMIPS4350
- bool "BMIPS4350"
- depends on SYS_HAS_CPU_BMIPS4350
- select CPU_BMIPS
- select SYS_SUPPORTS_SMP
- select SYS_SUPPORTS_HOTPLUG_CPU
- help
- Broadcom BMIPS4350 ("VIPER") processors.
-
-config CPU_BMIPS4380
- bool "BMIPS4380"
- depends on SYS_HAS_CPU_BMIPS4380
- select CPU_BMIPS
- select SYS_SUPPORTS_SMP
- select SYS_SUPPORTS_HOTPLUG_CPU
- help
- Broadcom BMIPS4380 processors.
-
-config CPU_BMIPS5000
- bool "BMIPS5000"
- depends on SYS_HAS_CPU_BMIPS5000
- select CPU_BMIPS
+config CPU_BMIPS
+ bool "Broadcom BMIPS"
+ depends on SYS_HAS_CPU_BMIPS
+ select CPU_MIPS32
+ select CPU_BMIPS32_3300 if SYS_HAS_CPU_BMIPS32_3300
+ select CPU_BMIPS4350 if SYS_HAS_CPU_BMIPS4350
+ select CPU_BMIPS4380 if SYS_HAS_CPU_BMIPS4380
+ select CPU_BMIPS5000 if SYS_HAS_CPU_BMIPS5000
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select SWAP_IO_SPACE
+ select WEAK_ORDERING
select CPU_SUPPORTS_HIGHMEM
- select MIPS_CPU_SCACHE
- select SYS_SUPPORTS_SMP
- select SYS_SUPPORTS_HOTPLUG_CPU
+ select CPU_HAS_PREFETCH
help
- Broadcom BMIPS5000 processors.
+ Support for BMIPS32/3300/4350/4380 and BMIPS5000 processors.
config CPU_XLR
bool "Netlogic XLR SoC"
@@ -1458,6 +1493,26 @@ config CPU_XLP
Netlogic Microsystems XLP processors.
endchoice
+config CPU_MIPS32_3_5_FEATURES
+ bool "MIPS32 Release 3.5 Features"
+ depends on SYS_HAS_CPU_MIPS32_R3_5
+ depends on CPU_MIPS32_R2
+ help
+ Choose this option to build a kernel for release 2 or later of the
+ MIPS32 architecture including features from the 3.5 release such as
+ support for Enhanced Virtual Addressing (EVA).
+
+config CPU_MIPS32_3_5_EVA
+ bool "Enhanced Virtual Addressing (EVA)"
+ depends on CPU_MIPS32_3_5_FEATURES
+ select EVA
+ default y
+ help
+ Choose this option if you want to enable the Enhanced Virtual
+ Addressing (EVA) on your MIPS32 core (such as proAptiv).
+ One of its primary benefits is an increase in the maximum size
+ of lowmem (up to 3GB). If unsure, say 'N' here.
+
if CPU_LOONGSON2F
config CPU_NOP_WORKAROUNDS
bool
@@ -1489,8 +1544,10 @@ config SYS_SUPPORTS_ZBOOT
bool
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_BZIP2
+ select HAVE_KERNEL_LZ4
select HAVE_KERNEL_LZMA
select HAVE_KERNEL_LZO
+ select HAVE_KERNEL_XZ
config SYS_SUPPORTS_ZBOOT_UART16550
bool
@@ -1511,14 +1568,29 @@ config CPU_LOONGSON1
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
-config CPU_BMIPS
+config CPU_BMIPS32_3300
+ select SMP_UP if SMP
bool
- select CPU_MIPS32
- select CPU_SUPPORTS_32BIT_KERNEL
- select DMA_NONCOHERENT
- select IRQ_CPU
- select SWAP_IO_SPACE
- select WEAK_ORDERING
+
+config CPU_BMIPS4350
+ bool
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_HOTPLUG_CPU
+
+config CPU_BMIPS4380
+ bool
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_HOTPLUG_CPU
+
+config CPU_BMIPS5000
+ bool
+ select MIPS_CPU_SCACHE
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_HOTPLUG_CPU
+
+config SYS_HAS_CPU_LOONGSON3
+ bool
+ select CPU_SUPPORTS_CPUFREQ
config SYS_HAS_CPU_LOONGSON2E
bool
@@ -1538,6 +1610,9 @@ config SYS_HAS_CPU_MIPS32_R1
config SYS_HAS_CPU_MIPS32_R2
bool
+config SYS_HAS_CPU_MIPS32_R3_5
+ bool
+
config SYS_HAS_CPU_MIPS64_R1
bool
@@ -1592,17 +1667,24 @@ config SYS_HAS_CPU_SB1
config SYS_HAS_CPU_CAVIUM_OCTEON
bool
-config SYS_HAS_CPU_BMIPS3300
+config SYS_HAS_CPU_BMIPS
+ bool
+
+config SYS_HAS_CPU_BMIPS32_3300
bool
+ select SYS_HAS_CPU_BMIPS
config SYS_HAS_CPU_BMIPS4350
bool
+ select SYS_HAS_CPU_BMIPS
config SYS_HAS_CPU_BMIPS4380
bool
+ select SYS_HAS_CPU_BMIPS
config SYS_HAS_CPU_BMIPS5000
bool
+ select SYS_HAS_CPU_BMIPS
config SYS_HAS_CPU_XLR
bool
@@ -1610,6 +1692,12 @@ config SYS_HAS_CPU_XLR
config SYS_HAS_CPU_XLP
bool
+config MIPS_MALTA_PM
+ depends on MIPS_MALTA
+ depends on PCI
+ bool
+ default y
+
#
# CPU may reorder R->R, R->W, W->R, W->W
# Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC
@@ -1647,6 +1735,9 @@ config CPU_MIPSR2
bool
default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
+config EVA
+ bool
+
config SYS_SUPPORTS_32BIT_KERNEL
bool
config SYS_SUPPORTS_64BIT_KERNEL
@@ -1704,14 +1795,14 @@ config KVM_GUEST
help
Select this option if building a guest kernel for KVM (Trap & Emulate) mode
-config KVM_HOST_FREQ
- int "KVM Host Processor Frequency (MHz)"
+config KVM_GUEST_TIMER_FREQ
+ int "Count/Compare Timer Frequency (MHz)"
depends on KVM_GUEST
- default 500
+ default 100
help
- Select this option if building a guest kernel for KVM to skip
- RTC emulation when determining guest CPU Frequency. Instead, the guest
- processor frequency is automatically derived from the host frequency.
+ Set this to non-zero if building a guest kernel for KVM to skip RTC
+ emulation when determining guest CPU Frequency. Instead, the guest's
+ timer frequency is specified directly.
choice
prompt "Kernel page size"
@@ -1719,7 +1810,7 @@ choice
config PAGE_SIZE_4KB
bool "4kB"
- depends on !CPU_LOONGSON2
+ depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
help
This option select the standard 4kB Linux page size. On some
R3000-family processors this is the only available page size. Using
@@ -1766,12 +1857,12 @@ endchoice
config FORCE_MAX_ZONEORDER
int "Maximum zone order"
- range 14 64 if HUGETLB_PAGE && PAGE_SIZE_64KB
- default "14" if HUGETLB_PAGE && PAGE_SIZE_64KB
- range 13 64 if HUGETLB_PAGE && PAGE_SIZE_32KB
- default "13" if HUGETLB_PAGE && PAGE_SIZE_32KB
- range 12 64 if HUGETLB_PAGE && PAGE_SIZE_16KB
- default "12" if HUGETLB_PAGE && PAGE_SIZE_16KB
+ range 14 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_64KB
+ default "14" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_64KB
+ range 13 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_32KB
+ default "13" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_32KB
+ range 12 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_16KB
+ default "12" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_16KB
range 11 64
default "11"
help
@@ -1790,7 +1881,7 @@ config FORCE_MAX_ZONEORDER
config CEVT_GIC
bool "Use GIC global counter for clock events"
- depends on IRQ_GIC && !(MIPS_SEAD3 || MIPS_MT_SMTC)
+ depends on IRQ_GIC && !MIPS_SEAD3
help
Use the GIC global counter for the clock events. The R4K clock
event driver is always present, so if the platform ends up not
@@ -1810,6 +1901,7 @@ config IP22_CPU_SCACHE
config MIPS_CPU_SCACHE
bool
select BOARD_SCACHE
+ select MIPS_L1_CACHE_SHIFT_6
config R5000_CPU_SCACHE
bool
@@ -1842,65 +1934,25 @@ config CPU_R4K_CACHE_TLB
bool
default y if !(CPU_R3000 || CPU_R8000 || CPU_SB1 || CPU_TX39XX || CPU_CAVIUM_OCTEON)
-choice
- prompt "MIPS MT options"
-
-config MIPS_MT_DISABLED
- bool "Disable multithreading support."
- help
- Use this option if your workload can't take advantage of
- MIPS hardware multithreading support. On systems that don't have
- the option of an MT-enabled processor this option will be the only
- option in this menu.
-
config MIPS_MT_SMP
- bool "Use 1 TC on each available VPE for SMP"
+ bool "MIPS MT SMP support (1 TC on each available VPE)"
depends on SYS_SUPPORTS_MULTITHREADING
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
+ select SYNC_R4K
+ select MIPS_GIC_IPI
select MIPS_MT
select SMP
- select SYS_SUPPORTS_SCHED_SMT if SMP
- select SYS_SUPPORTS_SMP
select SMP_UP
- select MIPS_PERF_SHARED_TC_COUNTERS
- help
- This is a kernel model which is known a VSMP but lately has been
- marketesed into SMVP.
- Virtual SMP uses the processor's VPEs to implement virtual
- processors. In currently available configuration of the 34K processor
- this allows for a dual processor. Both processors will share the same
- primary caches; each will obtain the half of the TLB for it's own
- exclusive use. For a layman this model can be described as similar to
- what Intel calls Hyperthreading.
-
- For further information see http://www.linux-mips.org/wiki/34K#VSMP
-
-config MIPS_MT_SMTC
- bool "SMTC: Use all TCs on all VPEs for SMP"
- depends on CPU_MIPS32_R2
- #depends on CPU_MIPS64_R2 # once there is hardware ...
- depends on SYS_SUPPORTS_MULTITHREADING
- select CPU_MIPSR2_IRQ_VI
- select CPU_MIPSR2_IRQ_EI
- select MIPS_MT
- select NR_CPUS_DEFAULT_8
- select SMP
select SYS_SUPPORTS_SMP
- select SMP_UP
+ select SYS_SUPPORTS_SCHED_SMT
+ select MIPS_PERF_SHARED_TC_COUNTERS
help
- This is a kernel model which is known a SMTC or lately has been
- marketesed into SMVP.
- is presenting the available TC's of the core as processors to Linux.
- On currently available 34K processors this means a Linux system will
- see up to 5 processors. The implementation of the SMTC kernel differs
- significantly from VSMP and cannot efficiently coexist in the same
- kernel binary so the choice between VSMP and SMTC is a compile time
- decision.
-
- For further information see http://www.linux-mips.org/wiki/34K#SMTC
-
-endchoice
+ This is a kernel model which is known as SMVP. This is supported
+ on cores with the MT ASE and uses the available VPEs to implement
+ virtual processors which supports SMP. This is equivalent to the
+ Intel Hyperthreading feature. For further information go to
+ <http://www.imgtec.com/mips/mips-multithreading.asp>.
config MIPS_MT
bool
@@ -1923,7 +1975,7 @@ config SYS_SUPPORTS_MULTITHREADING
config MIPS_MT_FPAFF
bool "Dynamic FPU affinity for FP-intensive threads"
default y
- depends on MIPS_MT_SMP || MIPS_MT_SMTC
+ depends on MIPS_MT_SMP
config MIPS_VPE_LOADER
bool "VPE loader support."
@@ -1935,28 +1987,15 @@ config MIPS_VPE_LOADER
Includes a loader for loading an elf relocatable object
onto another VPE and running it.
-config MIPS_MT_SMTC_IM_BACKSTOP
- bool "Use per-TC register bits as backstop for inhibited IM bits"
- depends on MIPS_MT_SMTC
- default n
- help
- To support multiple TC microthreads acting as "CPUs" within
- a VPE, VPE-wide interrupt mask bits must be specially manipulated
- during interrupt handling. To support legacy drivers and interrupt
- controller management code, SMTC has a "backstop" to track and
- if necessary restore the interrupt mask. This has some performance
- impact on interrupt service overhead.
+config MIPS_VPE_LOADER_CMP
+ bool
+ default "y"
+ depends on MIPS_VPE_LOADER && MIPS_CMP
-config MIPS_MT_SMTC_IRQAFF
- bool "Support IRQ affinity API"
- depends on MIPS_MT_SMTC
- default n
- help
- Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)
- for SMTC Linux kernel. Requires platform support, of which
- an example can be found in the MIPS kernel i8259 and Malta
- platform code. Adds some overhead to interrupt dispatch, and
- should be used only if you know what you are doing.
+config MIPS_VPE_LOADER_MT
+ bool
+ default "y"
+ depends on MIPS_VPE_LOADER && !MIPS_CMP
config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux"
@@ -1968,23 +2007,66 @@ config MIPS_VPE_LOADER_TOM
you to ensure the amount you put in the option and the space your
program requires is less or equal to the amount physically present.
-# this should possibly be in drivers/char, but it is rather cpu related. Hmmm
config MIPS_VPE_APSP_API
bool "Enable support for AP/SP API (RTLX)"
depends on MIPS_VPE_LOADER
help
+config MIPS_VPE_APSP_API_CMP
+ bool
+ default "y"
+ depends on MIPS_VPE_APSP_API && MIPS_CMP
+
+config MIPS_VPE_APSP_API_MT
+ bool
+ default "y"
+ depends on MIPS_VPE_APSP_API && !MIPS_CMP
+
config MIPS_CMP
- bool "MIPS CMP framework support"
+ bool "MIPS CMP framework support (DEPRECATED)"
depends on SYS_SUPPORTS_MIPS_CMP
+ select MIPS_GIC_IPI
select SYNC_R4K
- select SYS_SUPPORTS_SMP
- select SYS_SUPPORTS_SCHED_SMT if SMP
select WEAK_ORDERING
default n
help
- This is a placeholder option for the GCMP work. It will need to
- be handled differently...
+ Select this if you are using a bootloader which implements the "CMP
+ framework" protocol (ie. YAMON) and want your kernel to make use of
+ its ability to start secondary CPUs.
+
+ Unless you have a specific need, you should use CONFIG_MIPS_CPS
+ instead of this.
+
+config MIPS_CPS
+ bool "MIPS Coherent Processing System support"
+ depends on SYS_SUPPORTS_MIPS_CPS
+ select MIPS_CM
+ select MIPS_CPC
+ select MIPS_CPS_PM if HOTPLUG_CPU
+ select MIPS_GIC_IPI
+ select SMP
+ select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
+ select SYS_SUPPORTS_HOTPLUG_CPU
+ select SYS_SUPPORTS_SMP
+ select WEAK_ORDERING
+ help
+ Select this if you wish to run an SMP kernel across multiple cores
+ within a MIPS Coherent Processing System. When this option is
+ enabled the kernel will probe for other cores and boot them with
+ no external assistance. It is safe to enable this when hardware
+ support is unavailable.
+
+config MIPS_CPS_PM
+ bool
+
+config MIPS_GIC_IPI
+ bool
+
+config MIPS_CM
+ bool
+
+config MIPS_CPC
+ bool
config SB1_PASS_1_WORKAROUNDS
bool
@@ -2027,6 +2109,21 @@ config CPU_MICROMIPS
When this option is enabled the kernel will be built using the
microMIPS ISA
+config CPU_HAS_MSA
+ bool "Support for the MIPS SIMD Architecture"
+ depends on CPU_SUPPORTS_MSA
+ default y
+ help
+ MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
+ and a set of SIMD instructions to operate on them. When this option
+ is enabled the kernel will support allocating & switching MSA
+ vector register contexts. If you know that your kernel will only be
+ running on CPUs which do not support MSA or that your userland will
+ not be making use of it then you may wish to say N here to reduce
+ the size & complexity of your kernel.
+
+ If unsure, say Y.
+
config CPU_HAS_WB
bool
@@ -2078,7 +2175,7 @@ config CPU_R4400_WORKAROUNDS
#
config HIGHMEM
bool "High Memory Support"
- depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM
+ depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA
config CPU_SUPPORTS_HIGHMEM
bool
@@ -2092,6 +2189,16 @@ config SYS_SUPPORTS_SMARTMIPS
config SYS_SUPPORTS_MICROMIPS
bool
+config SYS_SUPPORTS_MIPS16
+ bool
+ help
+ This option must be set if a kernel might be executed on a MIPS16-
+ enabled CPU even if MIPS16 is not actually being used. In other
+ words, it makes the kernel MIPS16-tolerant.
+
+config CPU_SUPPORTS_MSA
+ bool
+
config ARCH_FLATMEM_ENABLE
def_bool y
depends on !NUMA && !CPU_LOONGSON2
@@ -2129,7 +2236,7 @@ config NODES_SHIFT
config HW_PERF_EVENTS
bool "Enable hardware performance counter support for perf events"
- depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP)
+ depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP)
default y
help
Enable hardware performance counter support for perf events. If
@@ -2140,16 +2247,15 @@ source "mm/Kconfig"
config SMP
bool "Multi-Processing support"
depends on SYS_SUPPORTS_SMP
- select USE_GENERIC_SMP_HELPERS
help
This enables support for systems with more than one CPU. If you have
- a system with only one CPU, like most personal computers, say N. If
- you have a system with more than one CPU, say Y.
+ a system with only one CPU, say N. If you have a system with more
+ than one CPU, say Y.
- If you say N here, the kernel will run on single and multiprocessor
+ If you say N here, the kernel will run on uni- and multiprocessor
machines, but will use only one CPU of a multiprocessor machine. If
you say Y here, the kernel will run on many, but not all,
- singleprocessor machines. On a singleprocessor machine, the kernel
+ uniprocessor machines. On a uniprocessor machine, the kernel
will run faster if you say N here.
People using multiprocessor machines who say Y here should also say
@@ -2166,6 +2272,9 @@ config SMP_UP
config SYS_SUPPORTS_MIPS_CMP
bool
+config SYS_SUPPORTS_MIPS_CPS
+ bool
+
config SYS_SUPPORTS_SMP
bool
@@ -2185,8 +2294,8 @@ config NR_CPUS_DEFAULT_64
bool
config NR_CPUS
- int "Maximum number of CPUs (2-64)"
- range 2 64
+ int "Maximum number of CPUs (2-256)"
+ range 2 256
depends on SMP
default "4" if NR_CPUS_DEFAULT_4
default "8" if NR_CPUS_DEFAULT_8
@@ -2337,18 +2446,28 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
-config CC_STACKPROTECTOR
- bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
- help
- This option turns on the -fstack-protector GCC feature. This
- feature puts, at the beginning of functions, a canary value on
- the stack just before the return address, and validates
- the value just before actually returning. Stack based buffer
- overflows (that need to overwrite this return address) now also
- overwrite the canary, which gets detected and the attack is then
- neutralized via a kernel panic.
+config MIPS_O32_FP64_SUPPORT
+ bool "Support for O32 binaries using 64-bit FP (EXPERIMENTAL)"
+ depends on 32BIT || MIPS32_O32
+ help
+ When this is enabled, the kernel will support use of 64-bit floating
+ point registers with binaries using the O32 ABI along with the
+ EF_MIPS_FP64 ELF header flag (typically built with -mfp64). On
+ 32-bit MIPS systems this support is at the cost of increasing the
+ size and complexity of the compiled FPU emulator. Thus if you are
+ running a MIPS32 system and know that none of your userland binaries
+ will require 64-bit floating point, you may wish to reduce the size
+ of your kernel & potentially improve FP emulation performance by
+ saying N here.
+
+ Although binutils currently supports use of this flag the details
+ concerning its effect upon the O32 ABI in userland are still being
+ worked on. In order to avoid userland becoming dependant upon current
+ behaviour before the details have been finalised, this option should
+ be considered experimental and only enabled by those working upon
+ said details.
- This feature requires gcc version 4.2 or above.
+ If unsure, say N.
config USE_OF
bool
@@ -2388,6 +2507,17 @@ config PCI
your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
say Y, otherwise N.
+config HT_PCI
+ bool "Support for HT-linked PCI"
+ default y
+ depends on CPU_LOONGSON3
+ select PCI
+ select PCI_DOMAINS
+ help
+ Loongson family machines use Hyper-Transport bus for inter-core
+ connection and device connection. The PCI bus is a subordinate
+ linked at HT. Choose Y for Loongson-3 based machines.
+
config PCI_DOMAINS
bool
@@ -2457,7 +2587,7 @@ source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig"
config RAPIDIO
- bool "RapidIO support"
+ tristate "RapidIO support"
depends on PCI
default n
help
@@ -2538,12 +2668,16 @@ endmenu
config MIPS_EXTERNAL_TIMER
bool
-if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
menu "CPU Power Management"
+
+if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
source "drivers/cpufreq/Kconfig"
-endmenu
endif
+source "drivers/cpuidle/Kconfig"
+
+endmenu
+
source "net/Kconfig"
source "drivers/Kconfig"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 37871f0de15..3a2b775e845 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -20,6 +20,18 @@ config EARLY_PRINTK
doesn't cooperate with an X server. You should normally say N here,
unless you want to debug such a crash.
+config EARLY_PRINTK_8250
+ bool
+ depends on EARLY_PRINTK && USE_GENERIC_EARLY_PRINTK_8250
+ default y
+ help
+ "8250/16550 and compatible serial early printk driver"
+ If you say Y here, it will be possible to use a 8250/16550 serial
+ port as the boot console.
+
+config USE_GENERIC_EARLY_PRINTK_8250
+ bool
+
config CMDLINE_BOOL
bool "Built-in kernel command line"
default n
@@ -67,15 +79,6 @@ config CMDLINE_OVERRIDE
Normally, you will choose 'N' here.
-config SMTC_IDLE_HOOK_DEBUG
- bool "Enable additional debug checks before going into CPU idle loop"
- depends on DEBUG_KERNEL && MIPS_MT_SMTC
- help
- This option enables Enable additional debug checks before going into
- CPU idle loop. For details on these checks, see
- arch/mips/kernel/smtc.c. This debugging option result in significant
- overhead so should be disabled in production kernels.
-
config SB1XXX_CORELIS
bool "Corelis Debugger"
depends on SIBYTE_SB1xxx_SOC
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 75a36ad11ff..a8521de1479 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -114,11 +114,16 @@ cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*e
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
cflags-$(CONFIG_CPU_HAS_SMARTMIPS) += $(call cc-option,-msmartmips)
-cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips -mno-jals)
+cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips)
cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \
-fno-omit-frame-pointer
+ifeq ($(CONFIG_CPU_HAS_MSA),y)
+toolchain-msa := $(call cc-option-yn,-mhard-float -mfp64 -Wa$(comma)-mmsa)
+cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA
+endif
+
#
# CPU-dependent compiler/assembler options for optimization.
#
@@ -146,7 +151,7 @@ cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \
-Wa,--trap
cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \
-Wa,--trap
-cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \
+cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1 -mno-mdmx -mno-mips3d,-march=r5000) \
-Wa,--trap
cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap
cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \
@@ -232,10 +237,6 @@ bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \
LDFLAGS += -m $(ld-emul)
-ifdef CONFIG_CC_STACKPROTECTOR
- KBUILD_CFLAGS += -fstack-protector
-endif
-
ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
@@ -250,6 +251,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo
head-y := arch/mips/kernel/head.o
libs-y += arch/mips/lib/
+libs-y += arch/mips/math-emu/
# See arch/mips/Kbuild for content of core part of the kernel
core-y += arch/mips/
@@ -285,18 +287,19 @@ endif
# Other need ECOFF, so we build a 32-bit ELF binary for them which we then
# convert to ECOFF using elf2ecoff.
#
+quiet_cmd_32 = OBJCOPY $@
+ cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
vmlinux.32: vmlinux
- $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
-
-
-#obj-$(CONFIG_KPROBES) += kprobes.o
+ $(call cmd,32)
#
# The 64-bit ELF tools are pretty broken so at this time we generate 64-bit
# ELF files from 32-bit files by conversion.
#
+quiet_cmd_64 = OBJCOPY $@
+ cmd_64 = $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
vmlinux.64: vmlinux
- $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
+ $(call cmd,64)
all: $(all-y)
@@ -305,10 +308,16 @@ $(boot-y): $(vmlinux-32) FORCE
$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \
$(bootvars-y) arch/mips/boot/$@
+ifdef CONFIG_SYS_SUPPORTS_ZBOOT
# boot/compressed
$(bootz-y): $(vmlinux-32) FORCE
$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \
$(bootvars-y) 32bit-bfd=$(32bit-bfd) $@
+else
+vmlinuz: FORCE
+ @echo ' CONFIG_SYS_SUPPORTS_ZBOOT is not enabled'
+ /bin/false
+endif
CLEAN_FILES += vmlinux.32 vmlinux.64
diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig
index 7032ac7ecd1..b9628983d62 100644
--- a/arch/mips/alchemy/Kconfig
+++ b/arch/mips/alchemy/Kconfig
@@ -16,36 +16,29 @@ config ALCHEMY_GPIO_INDIRECT
choice
prompt "Machine type"
depends on MIPS_ALCHEMY
- default MIPS_DB1000
+ default MIPS_DB1XXX
config MIPS_MTX1
bool "4G Systems MTX-1 board"
- select DMA_NONCOHERENT
select HW_HAS_PCI
select ALCHEMY_GPIOINT_AU1000
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_HAS_EARLY_PRINTK
-config MIPS_DB1000
- bool "Alchemy DB1000/DB1500/DB1100 PB1500/1100 boards"
- select ALCHEMY_GPIOINT_AU1000
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_LITTLE_ENDIAN
- select SYS_HAS_EARLY_PRINTK
-
-config MIPS_DB1235
- bool "Alchemy DB1200/PB1200/DB1300/DB1550/PB1550 boards"
+config MIPS_DB1XXX
+ bool "Alchemy DB1XXX / PB1XXX boards"
select ARCH_REQUIRE_GPIOLIB
select HW_HAS_PCI
- select DMA_COHERENT
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_HAS_EARLY_PRINTK
+ help
+ Select this option if you have one of the following Alchemy
+ development boards: DB1000 DB1500 DB1100 DB1550 DB1200 DB1300
+ PB1500 PB1100 PB1550 PB1200
+ Board type is autodetected during boot.
config MIPS_XXS1500
bool "MyCable XXS1500 board"
- select DMA_NONCOHERENT
select ALCHEMY_GPIOINT_AU1000
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_HAS_EARLY_PRINTK
@@ -54,7 +47,6 @@ config MIPS_GPR
bool "Trapeze ITS GPR board"
select ALCHEMY_GPIOINT_AU1000
select HW_HAS_PCI
- select DMA_NONCOHERENT
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_HAS_EARLY_PRINTK
diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform
index b3afcdd8d77..33c9da3b077 100644
--- a/arch/mips/alchemy/Platform
+++ b/arch/mips/alchemy/Platform
@@ -5,18 +5,12 @@ platform-$(CONFIG_MIPS_ALCHEMY) += alchemy/common/
#
-# AMD Alchemy Db1000/Db1500/Pb1500/Db1100/Pb1100 eval boards
+# AMD Alchemy Db1000/Db1500/Pb1500/Db1100/Pb1100
+# Db1550/Pb1550/Db1200/Pb1200/Db1300
#
-platform-$(CONFIG_MIPS_DB1000) += alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000
-
-#
-# AMD Alchemy Db1200/Pb1200/Db1550/Pb1550/Db1300 eval boards
-#
-platform-$(CONFIG_MIPS_DB1235) += alchemy/devboards/
-cflags-$(CONFIG_MIPS_DB1235) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
-load-$(CONFIG_MIPS_DB1235) += 0xffffffff80100000
+platform-$(CONFIG_MIPS_DB1XXX) += alchemy/devboards/
+cflags-$(CONFIG_MIPS_DB1XXX) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
+load-$(CONFIG_MIPS_DB1XXX) += 0xffffffff80100000
#
# 4G-Systems MTX-1 "MeshCube" wireless router
diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
index 9edc35ff8cf..acf9a2a37f5 100644
--- a/arch/mips/alchemy/board-gpr.c
+++ b/arch/mips/alchemy/board-gpr.c
@@ -53,10 +53,8 @@ void __init prom_init(void)
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
- if (!memsize_str)
+ if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
memsize = 0x04000000;
- else
- strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index 4a9baa9f633..25a59a23547 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -52,10 +52,8 @@ void __init prom_init(void)
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
- if (!memsize_str)
+ if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
memsize = 0x04000000;
- else
- strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
@@ -276,7 +274,7 @@ static struct platform_device mtx1_pci_host = {
.resource = alchemy_pci_host_res,
};
-static struct __initdata platform_device * mtx1_devs[] = {
+static struct platform_device *mtx1_devs[] __initdata = {
&mtx1_pci_host,
&mtx1_gpio_leds,
&mtx1_wdt,
diff --git a/arch/mips/alchemy/board-xxs1500.c b/arch/mips/alchemy/board-xxs1500.c
index bd551365029..3fb814be0e9 100644
--- a/arch/mips/alchemy/board-xxs1500.c
+++ b/arch/mips/alchemy/board-xxs1500.c
@@ -49,7 +49,7 @@ void __init prom_init(void)
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
- if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
+ if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
memsize = 0x04000000;
add_memory_region(0, memsize, BOOT_MEM_RAM);
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index 0c7fce2a3c1..bdb28dee8fd 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -29,7 +29,6 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/init.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/jiffies.h>
diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c
index 62b4e7bbeab..8267e3c9772 100644
--- a/arch/mips/alchemy/common/setup.c
+++ b/arch/mips/alchemy/common/setup.c
@@ -30,6 +30,7 @@
#include <linux/jiffies.h>
#include <linux/module.h>
+#include <asm/dma-coherence.h>
#include <asm/mipsregs.h>
#include <asm/time.h>
@@ -59,6 +60,21 @@ void __init plat_mem_setup(void)
/* Clear to obtain best system bus performance */
clear_c0_config(1 << 19); /* Clear Config[OD] */
+ hw_coherentio = 0;
+ coherentio = 1;
+ switch (alchemy_get_cputype()) {
+ case ALCHEMY_CPU_AU1000:
+ case ALCHEMY_CPU_AU1500:
+ case ALCHEMY_CPU_AU1100:
+ coherentio = 0;
+ break;
+ case ALCHEMY_CPU_AU1200:
+ /* Au1200 AB USB does not support coherent memory */
+ if (0 == (read_c0_prid() & PRID_REV_MASK))
+ coherentio = 0;
+ break;
+ }
+
board_setup(); /* board specific setup */
/* IO/MEM resources. */
diff --git a/arch/mips/alchemy/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S
index 706d933e008..c73d81270b4 100644
--- a/arch/mips/alchemy/common/sleeper.S
+++ b/arch/mips/alchemy/common/sleeper.S
@@ -95,7 +95,7 @@ LEAF(alchemy_sleep_au1000)
/* cache following instructions, as memory gets put to sleep */
la t0, 1f
- .set mips3
+ .set arch=r4000
cache 0x14, 0(t0)
cache 0x14, 32(t0)
cache 0x14, 64(t0)
@@ -121,7 +121,7 @@ LEAF(alchemy_sleep_au1550)
/* cache following instructions, as memory gets put to sleep */
la t0, 1f
- .set mips3
+ .set arch=r4000
cache 0x14, 0(t0)
cache 0x14, 32(t0)
cache 0x14, 64(t0)
@@ -163,7 +163,7 @@ LEAF(alchemy_sleep_au1300)
la t1, 4f
subu t2, t1, t0
- .set mips3
+ .set arch=r4000
1: cache 0x14, 0(t0)
subu t2, t2, 32
diff --git a/arch/mips/alchemy/common/usb.c b/arch/mips/alchemy/common/usb.c
index fcc69562611..d193dbea84a 100644
--- a/arch/mips/alchemy/common/usb.c
+++ b/arch/mips/alchemy/common/usb.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/syscore_ops.h>
+#include <asm/cpu.h>
#include <asm/mach-au1x00/au1000.h>
/* control register offsets */
@@ -354,47 +355,25 @@ static inline void __au1200_udc_control(void __iomem *base, int enable)
}
}
-static inline int au1200_coherency_bug(void)
-{
-#if defined(CONFIG_DMA_COHERENT)
- /* Au1200 AB USB does not support coherent memory */
- if (!(read_c0_prid() & 0xff)) {
- printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n");
- printk(KERN_INFO "Au1200 USB: update your board or re-configure"
- " the kernel\n");
- return -ENODEV;
- }
-#endif
- return 0;
-}
-
static inline int au1200_usb_control(int block, int enable)
{
void __iomem *base =
(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
- int ret = 0;
switch (block) {
case ALCHEMY_USB_OHCI0:
- ret = au1200_coherency_bug();
- if (ret && enable)
- goto out;
__au1200_ohci_control(base, enable);
break;
case ALCHEMY_USB_UDC0:
__au1200_udc_control(base, enable);
break;
case ALCHEMY_USB_EHCI0:
- ret = au1200_coherency_bug();
- if (ret && enable)
- goto out;
__au1200_ehci_control(base, enable);
break;
default:
- ret = -ENODEV;
+ return -ENODEV;
}
-out:
- return ret;
+ return 0;
}
diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile
index 15bf7306648..9da3659a9d1 100644
--- a/arch/mips/alchemy/devboards/Makefile
+++ b/arch/mips/alchemy/devboards/Makefile
@@ -2,7 +2,5 @@
# Alchemy Develboards
#
-obj-y += bcsr.o platform.o
+obj-y += bcsr.o platform.o db1000.o db1200.o db1300.o db1550.o db1xxx.o
obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_MIPS_DB1000) += db1000.o
-obj-$(CONFIG_MIPS_DB1235) += db1235.o db1200.o db1300.o db1550.o
diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c
index 11f3ad20321..92dd929d405 100644
--- a/arch/mips/alchemy/devboards/db1000.c
+++ b/arch/mips/alchemy/devboards/db1000.c
@@ -41,42 +41,27 @@
#define F_SWAPPED (bcsr_read(BCSR_STATUS) & BCSR_STATUS_DB1000_SWAPBOOT)
-struct pci_dev;
+const char *get_system_type(void);
-static const char *board_type_str(void)
+int __init db1000_board_setup(void)
{
+ /* initialize board register space */
+ bcsr_init(DB1000_BCSR_PHYS_ADDR,
+ DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
+
switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
case BCSR_WHOAMI_DB1000:
- return "DB1000";
case BCSR_WHOAMI_DB1500:
- return "DB1500";
case BCSR_WHOAMI_DB1100:
- return "DB1100";
case BCSR_WHOAMI_PB1500:
case BCSR_WHOAMI_PB1500R2:
- return "PB1500";
case BCSR_WHOAMI_PB1100:
- return "PB1100";
- default:
- return "(unknown)";
+ pr_info("AMD Alchemy %s Board\n", get_system_type());
+ return 0;
}
+ return -ENODEV;
}
-const char *get_system_type(void)
-{
- return board_type_str();
-}
-
-void __init board_setup(void)
-{
- /* initialize board register space */
- bcsr_init(DB1000_BCSR_PHYS_ADDR,
- DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);
-
- printk(KERN_INFO "AMD Alchemy %s Board\n", board_type_str());
-}
-
-
static int db1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
{
if ((slot < 12) || (slot > 13) || pin == 0)
@@ -114,17 +99,10 @@ static struct platform_device db1500_pci_host_dev = {
.resource = alchemy_pci_host_res,
};
-static int __init db1500_pci_init(void)
+int __init db1500_pci_setup(void)
{
- int id = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
- if ((id == BCSR_WHOAMI_DB1500) || (id == BCSR_WHOAMI_PB1500) ||
- (id == BCSR_WHOAMI_PB1500R2))
- return platform_device_register(&db1500_pci_host_dev);
- return 0;
+ return platform_device_register(&db1500_pci_host_dev);
}
-/* must be arch_initcall; MIPS PCI scans busses in a subsys_initcall */
-arch_initcall(db1500_pci_init);
-
static struct resource au1100_lcd_resources[] = {
[0] = {
@@ -513,7 +491,7 @@ static struct platform_device *db1100_devs[] = {
&db1000_irda_dev,
};
-static int __init db1000_dev_init(void)
+int __init db1000_dev_setup(void)
{
int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
int c0, c1, d0, d1, s0, s1, flashsize = 32, twosocks = 1;
@@ -534,13 +512,10 @@ static int __init db1000_dev_init(void)
s0 = AU1100_GPIO1_INT;
s1 = AU1100_GPIO4_INT;
+ gpio_request(19, "sd0_cd");
+ gpio_request(20, "sd1_cd");
gpio_direction_input(19); /* sd0 cd# */
gpio_direction_input(20); /* sd1 cd# */
- gpio_direction_input(21); /* touch pendown# */
- gpio_direction_input(207); /* SPI MISO */
- gpio_direction_output(208, 0); /* SPI MOSI */
- gpio_direction_output(209, 1); /* SPI SCK */
- gpio_direction_output(210, 1); /* SPI CS# */
/* spi_gpio on SSI0 pins */
pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
@@ -626,4 +601,3 @@ static int __init db1000_dev_init(void)
db1x_register_norflash(flashsize << 20, 4 /* 32bit */, F_SWAPPED);
return 0;
}
-device_initcall(db1000_dev_init);
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index a84d98b8f96..9e46667f259 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -35,16 +35,63 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/smc91x.h>
+#include <linux/ata_platform.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1100_mmc.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1xxx_psc.h>
#include <asm/mach-au1x00/au1200fb.h>
#include <asm/mach-au1x00/au1550_spi.h>
#include <asm/mach-db1x00/bcsr.h>
-#include <asm/mach-db1x00/db1200.h>
#include "platform.h"
+#define BCSR_INT_IDE 0x0001
+#define BCSR_INT_ETH 0x0002
+#define BCSR_INT_PC0 0x0004
+#define BCSR_INT_PC0STSCHG 0x0008
+#define BCSR_INT_PC1 0x0010
+#define BCSR_INT_PC1STSCHG 0x0020
+#define BCSR_INT_DC 0x0040
+#define BCSR_INT_FLASHBUSY 0x0080
+#define BCSR_INT_PC0INSERT 0x0100
+#define BCSR_INT_PC0EJECT 0x0200
+#define BCSR_INT_PC1INSERT 0x0400
+#define BCSR_INT_PC1EJECT 0x0800
+#define BCSR_INT_SD0INSERT 0x1000
+#define BCSR_INT_SD0EJECT 0x2000
+#define BCSR_INT_SD1INSERT 0x4000
+#define BCSR_INT_SD1EJECT 0x8000
+
+#define DB1200_IDE_PHYS_ADDR 0x18800000
+#define DB1200_IDE_REG_SHIFT 5
+#define DB1200_IDE_PHYS_LEN (16 << DB1200_IDE_REG_SHIFT)
+#define DB1200_ETH_PHYS_ADDR 0x19000300
+#define DB1200_NAND_PHYS_ADDR 0x20000000
+
+#define PB1200_IDE_PHYS_ADDR 0x0C800000
+#define PB1200_ETH_PHYS_ADDR 0x0D000300
+#define PB1200_NAND_PHYS_ADDR 0x1C000000
+
+#define DB1200_INT_BEGIN (AU1000_MAX_INTR + 1)
+#define DB1200_IDE_INT (DB1200_INT_BEGIN + 0)
+#define DB1200_ETH_INT (DB1200_INT_BEGIN + 1)
+#define DB1200_PC0_INT (DB1200_INT_BEGIN + 2)
+#define DB1200_PC0_STSCHG_INT (DB1200_INT_BEGIN + 3)
+#define DB1200_PC1_INT (DB1200_INT_BEGIN + 4)
+#define DB1200_PC1_STSCHG_INT (DB1200_INT_BEGIN + 5)
+#define DB1200_DC_INT (DB1200_INT_BEGIN + 6)
+#define DB1200_FLASHBUSY_INT (DB1200_INT_BEGIN + 7)
+#define DB1200_PC0_INSERT_INT (DB1200_INT_BEGIN + 8)
+#define DB1200_PC0_EJECT_INT (DB1200_INT_BEGIN + 9)
+#define DB1200_PC1_INSERT_INT (DB1200_INT_BEGIN + 10)
+#define DB1200_PC1_EJECT_INT (DB1200_INT_BEGIN + 11)
+#define DB1200_SD0_INSERT_INT (DB1200_INT_BEGIN + 12)
+#define DB1200_SD0_EJECT_INT (DB1200_INT_BEGIN + 13)
+#define PB1200_SD1_INSERT_INT (DB1200_INT_BEGIN + 14)
+#define PB1200_SD1_EJECT_INT (DB1200_INT_BEGIN + 15)
+#define DB1200_INT_END (DB1200_INT_BEGIN + 15)
+
const char *get_system_type(void);
static int __init db1200_detect_board(void)
@@ -89,6 +136,15 @@ int __init db1200_board_setup(void)
return -ENODEV;
whoami = bcsr_read(BCSR_WHOAMI);
+ switch (BCSR_WHOAMI_BOARD(whoami)) {
+ case BCSR_WHOAMI_PB1200_DDR1:
+ case BCSR_WHOAMI_PB1200_DDR2:
+ case BCSR_WHOAMI_DB1200:
+ break;
+ default:
+ return -ENODEV;
+ }
+
printk(KERN_INFO "Alchemy/AMD/RMI %s Board, CPLD Rev %d"
" Board-ID %d Daughtercard ID %d\n", get_system_type(),
(whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
@@ -275,32 +331,38 @@ static struct platform_device db1200_eth_dev = {
/**********************************************************************/
+static struct pata_platform_info db1200_ide_info = {
+ .ioport_shift = DB1200_IDE_REG_SHIFT,
+};
+
+#define IDE_ALT_START (14 << DB1200_IDE_REG_SHIFT)
static struct resource db1200_ide_res[] = {
[0] = {
.start = DB1200_IDE_PHYS_ADDR,
- .end = DB1200_IDE_PHYS_ADDR + DB1200_IDE_PHYS_LEN - 1,
+ .end = DB1200_IDE_PHYS_ADDR + IDE_ALT_START - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
+ .start = DB1200_IDE_PHYS_ADDR + IDE_ALT_START,
+ .end = DB1200_IDE_PHYS_ADDR + DB1200_IDE_PHYS_LEN - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
.start = DB1200_IDE_INT,
.end = DB1200_IDE_INT,
.flags = IORESOURCE_IRQ,
},
- [2] = {
- .start = AU1200_DSCR_CMD0_DMA_REQ1,
- .end = AU1200_DSCR_CMD0_DMA_REQ1,
- .flags = IORESOURCE_DMA,
- },
};
static u64 au1200_ide_dmamask = DMA_BIT_MASK(32);
static struct platform_device db1200_ide_dev = {
- .name = "au1200-ide",
+ .name = "pata_platform",
.id = 0,
.dev = {
.dma_mask = &au1200_ide_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &db1200_ide_info,
},
.num_resources = ARRAY_SIZE(db1200_ide_res),
.resource = db1200_ide_res,
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index 6167e73eef9..1aed6be4de1 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -26,12 +26,44 @@
#include <asm/mach-au1x00/au1200fb.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
-#include <asm/mach-db1x00/db1300.h>
#include <asm/mach-db1x00/bcsr.h>
#include <asm/mach-au1x00/prom.h>
#include "platform.h"
+/* FPGA (external mux) interrupt sources */
+#define DB1300_FIRST_INT (ALCHEMY_GPIC_INT_LAST + 1)
+#define DB1300_IDE_INT (DB1300_FIRST_INT + 0)
+#define DB1300_ETH_INT (DB1300_FIRST_INT + 1)
+#define DB1300_CF_INT (DB1300_FIRST_INT + 2)
+#define DB1300_VIDEO_INT (DB1300_FIRST_INT + 4)
+#define DB1300_HDMI_INT (DB1300_FIRST_INT + 5)
+#define DB1300_DC_INT (DB1300_FIRST_INT + 6)
+#define DB1300_FLASH_INT (DB1300_FIRST_INT + 7)
+#define DB1300_CF_INSERT_INT (DB1300_FIRST_INT + 8)
+#define DB1300_CF_EJECT_INT (DB1300_FIRST_INT + 9)
+#define DB1300_AC97_INT (DB1300_FIRST_INT + 10)
+#define DB1300_AC97_PEN_INT (DB1300_FIRST_INT + 11)
+#define DB1300_SD1_INSERT_INT (DB1300_FIRST_INT + 12)
+#define DB1300_SD1_EJECT_INT (DB1300_FIRST_INT + 13)
+#define DB1300_OTG_VBUS_OC_INT (DB1300_FIRST_INT + 14)
+#define DB1300_HOST_VBUS_OC_INT (DB1300_FIRST_INT + 15)
+#define DB1300_LAST_INT (DB1300_FIRST_INT + 15)
+
+/* SMSC9210 CS */
+#define DB1300_ETH_PHYS_ADDR 0x19000000
+#define DB1300_ETH_PHYS_END 0x197fffff
+
+/* ATA CS */
+#define DB1300_IDE_PHYS_ADDR 0x18800000
+#define DB1300_IDE_REG_SHIFT 5
+#define DB1300_IDE_PHYS_LEN (16 << DB1300_IDE_REG_SHIFT)
+
+/* NAND CS */
+#define DB1300_NAND_PHYS_ADDR 0x20000000
+#define DB1300_NAND_PHYS_END 0x20000fff
+
+
static struct i2c_board_info db1300_i2c_devs[] __initdata = {
{ I2C_BOARD_INFO("wm8731", 0x1b), }, /* I2S audio codec */
{ I2C_BOARD_INFO("ne1619", 0x2d), }, /* adm1025-compat hwmon */
@@ -759,11 +791,15 @@ int __init db1300_board_setup(void)
{
unsigned short whoami;
- db1300_gpio_config();
bcsr_init(DB1300_BCSR_PHYS_ADDR,
DB1300_BCSR_PHYS_ADDR + DB1300_BCSR_HEXLED_OFS);
whoami = bcsr_read(BCSR_WHOAMI);
+ if (BCSR_WHOAMI_BOARD(whoami) != BCSR_WHOAMI_DB1300)
+ return -ENODEV;
+
+ db1300_gpio_config();
+
printk(KERN_INFO "NetLogic DBAu1300 Development Platform.\n\t"
"BoardID %d CPLD Rev %d DaughtercardID %d\n",
BCSR_WHOAMI_BOARD(whoami), BCSR_WHOAMI_CPLD(whoami),
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
index 016cddacd7e..bbd8d988470 100644
--- a/arch/mips/alchemy/devboards/db1550.c
+++ b/arch/mips/alchemy/devboards/db1550.c
@@ -62,10 +62,16 @@ int __init db1550_board_setup(void)
DB1550_BCSR_PHYS_ADDR + DB1550_BCSR_HEXLED_OFS);
whoami = bcsr_read(BCSR_WHOAMI); /* PB1550 hexled offset differs */
- if ((BCSR_WHOAMI_BOARD(whoami) == BCSR_WHOAMI_PB1550_SDR) ||
- (BCSR_WHOAMI_BOARD(whoami) == BCSR_WHOAMI_PB1550_DDR))
+ switch (BCSR_WHOAMI_BOARD(whoami)) {
+ case BCSR_WHOAMI_PB1550_SDR:
+ case BCSR_WHOAMI_PB1550_DDR:
bcsr_init(PB1550_BCSR_PHYS_ADDR,
PB1550_BCSR_PHYS_ADDR + PB1550_BCSR_HEXLED_OFS);
+ case BCSR_WHOAMI_DB1550:
+ break;
+ default:
+ return -ENODEV;
+ }
pr_info("Alchemy/AMD %s Board, CPLD Rev %d Board-ID %d " \
"Daughtercard ID %d\n", get_system_type(),
diff --git a/arch/mips/alchemy/devboards/db1235.c b/arch/mips/alchemy/devboards/db1xxx.c
index c76a90f7866..2d47f951121 100644
--- a/arch/mips/alchemy/devboards/db1235.c
+++ b/arch/mips/alchemy/devboards/db1xxx.c
@@ -1,12 +1,13 @@
/*
- * DB1200/PB1200 / DB1550 / DB1300 board support.
- *
- * These 4 boards can reliably be supported in a single kernel image.
+ * Alchemy DB/PB1xxx board support.
*/
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-db1x00/bcsr.h>
+int __init db1000_board_setup(void);
+int __init db1000_dev_setup(void);
+int __init db1500_pci_setup(void);
int __init db1200_board_setup(void);
int __init db1200_dev_setup(void);
int __init db1300_board_setup(void);
@@ -18,6 +19,17 @@ int __init db1550_pci_setup(int);
static const char *board_type_str(void)
{
switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
+ case BCSR_WHOAMI_DB1000:
+ return "DB1000";
+ case BCSR_WHOAMI_DB1500:
+ return "DB1500";
+ case BCSR_WHOAMI_DB1100:
+ return "DB1100";
+ case BCSR_WHOAMI_PB1500:
+ case BCSR_WHOAMI_PB1500R2:
+ return "PB1500";
+ case BCSR_WHOAMI_PB1100:
+ return "PB1100";
case BCSR_WHOAMI_PB1200_DDR1:
case BCSR_WHOAMI_PB1200_DDR2:
return "PB1200";
@@ -45,6 +57,11 @@ void __init board_setup(void)
int ret;
switch (alchemy_get_cputype()) {
+ case ALCHEMY_CPU_AU1000:
+ case ALCHEMY_CPU_AU1500:
+ case ALCHEMY_CPU_AU1100:
+ ret = db1000_board_setup();
+ break;
case ALCHEMY_CPU_AU1550:
ret = db1550_board_setup();
break;
@@ -59,10 +76,10 @@ void __init board_setup(void)
ret = -ENODEV;
}
if (ret)
- panic("cannot initialize board support\n");
+ panic("cannot initialize board support");
}
-int __init db1235_arch_init(void)
+static int __init db1xxx_arch_init(void)
{
int id = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
if (id == BCSR_WHOAMI_DB1550)
@@ -70,14 +87,24 @@ int __init db1235_arch_init(void)
else if ((id == BCSR_WHOAMI_PB1550_SDR) ||
(id == BCSR_WHOAMI_PB1550_DDR))
return db1550_pci_setup(1);
+ else if ((id == BCSR_WHOAMI_DB1500) || (id == BCSR_WHOAMI_PB1500) ||
+ (id == BCSR_WHOAMI_PB1500R2))
+ return db1500_pci_setup();
return 0;
}
-arch_initcall(db1235_arch_init);
+arch_initcall(db1xxx_arch_init);
-int __init db1235_dev_init(void)
+static int __init db1xxx_dev_init(void)
{
switch (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI))) {
+ case BCSR_WHOAMI_DB1000:
+ case BCSR_WHOAMI_DB1500:
+ case BCSR_WHOAMI_DB1100:
+ case BCSR_WHOAMI_PB1500:
+ case BCSR_WHOAMI_PB1500R2:
+ case BCSR_WHOAMI_PB1100:
+ return db1000_dev_setup();
case BCSR_WHOAMI_PB1200_DDR1:
case BCSR_WHOAMI_PB1200_DDR2:
case BCSR_WHOAMI_DB1200:
@@ -91,4 +118,4 @@ int __init db1235_dev_init(void)
}
return 0;
}
-device_initcall(db1235_dev_init);
+device_initcall(db1xxx_dev_init);
diff --git a/arch/mips/alchemy/devboards/pm.c b/arch/mips/alchemy/devboards/pm.c
index b86bff31d1d..61e90fe9eab 100644
--- a/arch/mips/alchemy/devboards/pm.c
+++ b/arch/mips/alchemy/devboards/pm.c
@@ -158,7 +158,7 @@ static ssize_t db1x_pmattr_store(struct kobject *kobj,
int tmp;
if (ATTRCMP(timer_timeout)) {
- tmp = strict_strtoul(instr, 0, &l);
+ tmp = kstrtoul(instr, 0, &l);
if (tmp)
return tmp;
@@ -181,7 +181,7 @@ static ssize_t db1x_pmattr_store(struct kobject *kobj,
}
} else if (ATTRCMP(wakemsk)) {
- tmp = strict_strtoul(instr, 0, &l);
+ tmp = kstrtoul(instr, 0, &l);
if (tmp)
return tmp;
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
index 9a357fffcfb..820b7a313d9 100644
--- a/arch/mips/ar7/setup.c
+++ b/arch/mips/ar7/setup.c
@@ -92,7 +92,6 @@ void __init plat_mem_setup(void)
_machine_restart = ar7_machine_restart;
_machine_halt = ar7_machine_halt;
pm_power_off = ar7_machine_power_off;
- panic_timeout = 3;
io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
if (!io_base)
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 3995e31a73e..dfc60209dc6 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -74,34 +74,26 @@ config ATH79_MACH_UBNT_XM
endmenu
config SOC_AR71XX
- select USB_ARCH_HAS_EHCI
- select USB_ARCH_HAS_OHCI
select HW_HAS_PCI
def_bool n
config SOC_AR724X
- select USB_ARCH_HAS_EHCI
- select USB_ARCH_HAS_OHCI
select HW_HAS_PCI
select PCI_AR724X if PCI
def_bool n
config SOC_AR913X
- select USB_ARCH_HAS_EHCI
def_bool n
config SOC_AR933X
- select USB_ARCH_HAS_EHCI
def_bool n
config SOC_AR934X
- select USB_ARCH_HAS_EHCI
select HW_HAS_PCI
select PCI_AR724X if PCI
def_bool n
config SOC_QCA955X
- select USB_ARCH_HAS_EHCI
select HW_HAS_PCI
select PCI_AR724X if PCI
def_bool n
diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h
index 648d2dafbc5..a3120714f0b 100644
--- a/arch/mips/ath79/common.h
+++ b/arch/mips/ath79/common.h
@@ -15,7 +15,6 @@
#define __ATH79_COMMON_H
#include <linux/types.h>
-#include <linux/init.h>
#define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024)
#define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024)
diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
index c3b04c929f2..516225d207e 100644
--- a/arch/mips/ath79/dev-common.c
+++ b/arch/mips/ath79/dev-common.c
@@ -20,7 +20,6 @@
#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ar933x_uart_platform.h>
#include "common.h"
#include "dev-common.h"
@@ -68,15 +67,11 @@ static struct resource ar933x_uart_resources[] = {
},
};
-static struct ar933x_uart_platform_data ar933x_uart_data;
static struct platform_device ar933x_uart_device = {
.name = "ar933x-uart",
.id = -1,
.resource = ar933x_uart_resources,
.num_resources = ARRAY_SIZE(ar933x_uart_resources),
- .dev = {
- .platform_data = &ar933x_uart_data,
- },
};
void __init ath79_register_uart(void)
@@ -93,7 +88,6 @@ void __init ath79_register_uart(void)
ath79_uart_data[0].uartclk = uart_clk_rate;
platform_device_register(&ath79_uart_device);
} else if (soc_is_ar933x()) {
- ar933x_uart_data.uartclk = uart_clk_rate;
platform_device_register(&ar933x_uart_device);
} else {
BUG();
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig
index 2b8b118398c..09cb6f7aa3d 100644
--- a/arch/mips/bcm47xx/Kconfig
+++ b/arch/mips/bcm47xx/Kconfig
@@ -2,6 +2,7 @@ if BCM47XX
config BCM47XX_SSB
bool "SSB Support for Broadcom BCM47XX"
+ select SYS_HAS_CPU_BMIPS32_3300
select SSB
select SSB_DRIVER_MIPS
select SSB_DRIVER_EXTIF
@@ -11,6 +12,7 @@ config BCM47XX_SSB
select SSB_PCICORE_HOSTMODE if PCI
select SSB_DRIVER_GPIO
select GPIOLIB
+ select LEDS_GPIO_REGISTER
default y
help
Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -20,6 +22,7 @@ config BCM47XX_SSB
config BCM47XX_BCMA
bool "BCMA Support for Broadcom BCM47XX"
select SYS_HAS_CPU_MIPS32_R2
+ select CPU_MIPSR2_IRQ_VI
select BCMA
select BCMA_HOST_SOC
select BCMA_DRIVER_MIPS
@@ -27,6 +30,7 @@ config BCM47XX_BCMA
select BCMA_DRIVER_PCI_HOSTMODE if PCI
select BCMA_DRIVER_GPIO
select GPIOLIB
+ select LEDS_GPIO_REGISTER
default y
help
Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index f3bf6d5bfb9..d58c51b5e50 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -4,4 +4,4 @@
#
obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
-obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
+obj-y += board.o buttons.o leds.o workarounds.o
diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h
new file mode 100644
index 00000000000..0194c3b9a72
--- /dev/null
+++ b/arch/mips/bcm47xx/bcm47xx_private.h
@@ -0,0 +1,15 @@
+#ifndef LINUX_BCM47XX_PRIVATE_H_
+#define LINUX_BCM47XX_PRIVATE_H_
+
+#include <linux/kernel.h>
+
+/* buttons.c */
+int __init bcm47xx_buttons_register(void);
+
+/* leds.c */
+void __init bcm47xx_leds_register(void);
+
+/* workarounds.c */
+void __init bcm47xx_workarounds(void);
+
+#endif
diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c
new file mode 100644
index 00000000000..44ab1be68c3
--- /dev/null
+++ b/arch/mips/bcm47xx/board.c
@@ -0,0 +1,335 @@
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/string.h>
+#include <bcm47xx_board.h>
+#include <bcm47xx_nvram.h>
+
+struct bcm47xx_board_type {
+ const enum bcm47xx_board board;
+ const char *name;
+};
+
+struct bcm47xx_board_type_list1 {
+ struct bcm47xx_board_type board;
+ const char *value1;
+};
+
+struct bcm47xx_board_type_list2 {
+ struct bcm47xx_board_type board;
+ const char *value1;
+ const char *value2;
+};
+
+struct bcm47xx_board_type_list3 {
+ struct bcm47xx_board_type board;
+ const char *value1;
+ const char *value2;
+ const char *value3;
+};
+
+struct bcm47xx_board_store {
+ enum bcm47xx_board board;
+ char name[BCM47XX_BOARD_MAX_NAME];
+};
+
+/* model_name */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_model_name[] __initconst = {
+ {{BCM47XX_BOARD_DLINK_DIR130, "D-Link DIR-130"}, "DIR-130"},
+ {{BCM47XX_BOARD_DLINK_DIR330, "D-Link DIR-330"}, "DIR-330"},
+ { {0}, NULL},
+};
+
+/* model_no */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_model_no[] __initconst = {
+ {{BCM47XX_BOARD_ASUS_WL700GE, "Asus WL700"}, "WL700"},
+ { {0}, NULL},
+};
+
+/* machine_name */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_machine_name[] __initconst = {
+ {{BCM47XX_BOARD_LINKSYS_WRTSL54GS, "Linksys WRTSL54GS"}, "WRTSL54GS"},
+ { {0}, NULL},
+};
+
+/* hardware_version */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
+ {{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"},
+ {{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
+ {{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"},
+ {{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"},
+ {{BCM47XX_BOARD_ASUS_RTN12D1, "Asus RT-N12D1"}, "RTN12D1"},
+ {{BCM47XX_BOARD_ASUS_RTN12HP, "Asus RT-N12HP"}, "RTN12HP"},
+ {{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16-"},
+ {{BCM47XX_BOARD_ASUS_WL320GE, "Asus WL320GE"}, "WL320G-"},
+ {{BCM47XX_BOARD_ASUS_WL330GE, "Asus WL330GE"}, "WL330GE-"},
+ {{BCM47XX_BOARD_ASUS_WL500GD, "Asus WL500GD"}, "WL500gd-"},
+ {{BCM47XX_BOARD_ASUS_WL500GPV1, "Asus WL500GP V1"}, "WL500gp-"},
+ {{BCM47XX_BOARD_ASUS_WL500GPV2, "Asus WL500GP V2"}, "WL500GPV2-"},
+ {{BCM47XX_BOARD_ASUS_WL500W, "Asus WL500W"}, "WL500gW-"},
+ {{BCM47XX_BOARD_ASUS_WL520GC, "Asus WL520GC"}, "WL520GC-"},
+ {{BCM47XX_BOARD_ASUS_WL520GU, "Asus WL520GU"}, "WL520GU-"},
+ {{BCM47XX_BOARD_BELKIN_F7D3301, "Belkin F7D3301"}, "F7D3301"},
+ {{BCM47XX_BOARD_BELKIN_F7D3302, "Belkin F7D3302"}, "F7D3302"},
+ {{BCM47XX_BOARD_BELKIN_F7D4301, "Belkin F7D4301"}, "F7D4301"},
+ {{BCM47XX_BOARD_BELKIN_F7D4302, "Belkin F7D4302"}, "F7D4302"},
+ {{BCM47XX_BOARD_BELKIN_F7D4401, "Belkin F7D4401"}, "F7D4401"},
+ { {0}, NULL},
+};
+
+/* productid */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
+ {{BCM47XX_BOARD_ASUS_RTAC66U, "Asus RT-AC66U"}, "RT-AC66U"},
+ {{BCM47XX_BOARD_ASUS_RTN10, "Asus RT-N10"}, "RT-N10"},
+ {{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RT-N10D"},
+ {{BCM47XX_BOARD_ASUS_RTN15U, "Asus RT-N15U"}, "RT-N15U"},
+ {{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16"},
+ {{BCM47XX_BOARD_ASUS_RTN53, "Asus RT-N53"}, "RT-N53"},
+ {{BCM47XX_BOARD_ASUS_RTN66U, "Asus RT-N66U"}, "RT-N66U"},
+ {{BCM47XX_BOARD_ASUS_WL300G, "Asus WL300G"}, "WL300g"},
+ {{BCM47XX_BOARD_ASUS_WLHDD, "Asus WLHDD"}, "WLHDD"},
+ { {0}, NULL},
+};
+
+/* ModelId */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
+ {{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
+ {{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
+ {{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
+ {{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
+ { {0}, NULL},
+};
+
+/* melco_id or buf1falo_id */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_melco_id[] __initconst = {
+ {{BCM47XX_BOARD_BUFFALO_WBR2_G54, "Buffalo WBR2-G54"}, "29bb0332"},
+ {{BCM47XX_BOARD_BUFFALO_WHR2_A54G54, "Buffalo WHR2-A54G54"}, "290441dd"},
+ {{BCM47XX_BOARD_BUFFALO_WHR_G125, "Buffalo WHR-G125"}, "32093"},
+ {{BCM47XX_BOARD_BUFFALO_WHR_G54S, "Buffalo WHR-G54S"}, "30182"},
+ {{BCM47XX_BOARD_BUFFALO_WHR_HP_G54, "Buffalo WHR-HP-G54"}, "30189"},
+ {{BCM47XX_BOARD_BUFFALO_WLA2_G54L, "Buffalo WLA2-G54L"}, "29129"},
+ {{BCM47XX_BOARD_BUFFALO_WZR_G300N, "Buffalo WZR-G300N"}, "31120"},
+ {{BCM47XX_BOARD_BUFFALO_WZR_RS_G54, "Buffalo WZR-RS-G54"}, "30083"},
+ {{BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP, "Buffalo WZR-RS-G54HP"}, "30103"},
+ { {0}, NULL},
+};
+
+/* boot_hw_model, boot_hw_ver */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_boot_hw[] __initconst = {
+ /* like WRT160N v3.0 */
+ {{BCM47XX_BOARD_CISCO_M10V1, "Cisco M10"}, "M10", "1.0"},
+ /* like WRT310N v2.0 */
+ {{BCM47XX_BOARD_CISCO_M20V1, "Cisco M20"}, "M20", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E900V1, "Linksys E900 V1"}, "E900", "1.0"},
+ /* like WRT160N v3.0 */
+ {{BCM47XX_BOARD_LINKSYS_E1000V1, "Linksys E1000 V1"}, "E100", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E1000V2, "Linksys E1000 V2"}, "E1000", "2.0"},
+ {{BCM47XX_BOARD_LINKSYS_E1000V21, "Linksys E1000 V2.1"}, "E1000", "2.1"},
+ {{BCM47XX_BOARD_LINKSYS_E1200V2, "Linksys E1200 V2"}, "E1200", "2.0"},
+ {{BCM47XX_BOARD_LINKSYS_E2000V1, "Linksys E2000 V1"}, "Linksys E2000", "1.0"},
+ /* like WRT610N v2.0 */
+ {{BCM47XX_BOARD_LINKSYS_E3000V1, "Linksys E3000 V1"}, "E300", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E3200V1, "Linksys E3200 V1"}, "E3200", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E4200V1, "Linksys E4200 V1"}, "E4200", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT150NV11, "Linksys WRT150N V1.1"}, "WRT150N", "1.1"},
+ {{BCM47XX_BOARD_LINKSYS_WRT150NV1, "Linksys WRT150N V1"}, "WRT150N", "1"},
+ {{BCM47XX_BOARD_LINKSYS_WRT160NV1, "Linksys WRT160N V1"}, "WRT160N", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT160NV3, "Linksys WRT160N V3"}, "WRT160N", "3.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT300NV11, "Linksys WRT300N V1.1"}, "WRT300N", "1.1"},
+ {{BCM47XX_BOARD_LINKSYS_WRT310NV1, "Linksys WRT310N V1"}, "WRT310N", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT310NV2, "Linksys WRT310N V2"}, "WRT310N", "2.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G3GV2, "Linksys WRT54G3GV2-VF"}, "WRT54G3GV2-VF", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT610NV1, "Linksys WRT610N V1"}, "WRT610N", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT610NV2, "Linksys WRT610N V2"}, "WRT610N", "2.0"},
+ { {0}, NULL},
+};
+
+/* board_id */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = {
+ {{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3300, "Netgear WNDR3300"}, "U12H093T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3400V1, "Netgear WNDR3400 V1"}, "U12H155T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3400V2, "Netgear WNDR3400 V2"}, "U12H187T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3400VCNA, "Netgear WNDR3400 Vcna"}, "U12H155T01_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3700V3, "Netgear WNDR3700 V3"}, "U12H194T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR4000, "Netgear WNDR4000"}, "U12H181T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR4500V1, "Netgear WNDR4500 V1"}, "U12H189T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR4500V2, "Netgear WNDR4500 V2"}, "U12H224T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR2000, "Netgear WNR2000"}, "U12H114T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "U12H136T99_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500U, "Netgear WNR3500U"}, "U12H136T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500V2, "Netgear WNR3500 V2"}, "U12H127T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500V2VC, "Netgear WNR3500 V2vc"}, "U12H127T70_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR834BV2, "Netgear WNR834B V2"}, "U12H081T00_NETGEAR"},
+ { {0}, NULL},
+};
+
+/* boardtype, boardnum, boardrev */
+static const
+struct bcm47xx_board_type_list3 bcm47xx_board_list_board[] __initconst = {
+ {{BCM47XX_BOARD_HUAWEI_E970, "Huawei E970"}, "0x048e", "0x5347", "0x11"},
+ {{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
+ {{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
+ { {0}, NULL},
+};
+
+/* boardtype, boardrev */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_board_type_rev[] __initconst = {
+ {{BCM47XX_BOARD_SIEMENS_SE505V2, "Siemens SE505 V2"}, "0x0101", "0x10"},
+ { {0}, NULL},
+};
+
+static const
+struct bcm47xx_board_type bcm47xx_board_unknown[] __initconst = {
+ {BCM47XX_BOARD_UNKNOWN, "Unknown Board"},
+};
+
+static struct bcm47xx_board_store bcm47xx_board = {BCM47XX_BOARD_NO, "Unknown Board"};
+
+static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
+{
+ char buf1[30];
+ char buf2[30];
+ char buf3[30];
+ const struct bcm47xx_board_type_list1 *e1;
+ const struct bcm47xx_board_type_list2 *e2;
+ const struct bcm47xx_board_type_list3 *e3;
+
+ if (bcm47xx_nvram_getenv("model_name", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_model_name; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("model_no", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_model_no; e1->value1; e1++) {
+ if (strstarts(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("machine_name", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_machine_name; e1->value1; e1++) {
+ if (strstarts(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_hardware_version; e1->value1; e1++) {
+ if (strstarts(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("ModelId", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_ModelId; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("melco_id", buf1, sizeof(buf1)) >= 0 ||
+ bcm47xx_nvram_getenv("buf1falo_id", buf1, sizeof(buf1)) >= 0) {
+ /* buffalo hardware, check id for specific hardware matches */
+ for (e1 = bcm47xx_board_list_melco_id; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("boot_hw_model", buf1, sizeof(buf1)) >= 0 &&
+ bcm47xx_nvram_getenv("boot_hw_ver", buf2, sizeof(buf2)) >= 0) {
+ for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
+ if (!strcmp(buf1, e2->value1) &&
+ !strcmp(buf2, e2->value2))
+ return &e2->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("board_id", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_board_id; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
+ bcm47xx_nvram_getenv("boardnum", buf2, sizeof(buf2)) >= 0 &&
+ bcm47xx_nvram_getenv("boardrev", buf3, sizeof(buf3)) >= 0) {
+ for (e3 = bcm47xx_board_list_board; e3->value1; e3++) {
+ if (!strcmp(buf1, e3->value1) &&
+ !strcmp(buf2, e3->value2) &&
+ !strcmp(buf3, e3->value3))
+ return &e3->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
+ bcm47xx_nvram_getenv("boardrev", buf2, sizeof(buf2)) >= 0 &&
+ bcm47xx_nvram_getenv("boardnum", buf3, sizeof(buf3)) == -ENOENT) {
+ for (e2 = bcm47xx_board_list_board_type_rev; e2->value1; e2++) {
+ if (!strcmp(buf1, e2->value1) &&
+ !strcmp(buf2, e2->value2))
+ return &e2->board;
+ }
+ }
+ return bcm47xx_board_unknown;
+}
+
+void __init bcm47xx_board_detect(void)
+{
+ int err;
+ char buf[10];
+ const struct bcm47xx_board_type *board_detected;
+
+ if (bcm47xx_board.board != BCM47XX_BOARD_NO)
+ return;
+
+ /* check if the nvram is available */
+ err = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
+
+ /* init of nvram failed, probably too early now */
+ if (err == -ENXIO) {
+ return;
+ }
+
+ board_detected = bcm47xx_board_get_nvram();
+ bcm47xx_board.board = board_detected->board;
+ strlcpy(bcm47xx_board.name, board_detected->name,
+ BCM47XX_BOARD_MAX_NAME);
+}
+
+enum bcm47xx_board bcm47xx_board_get(void)
+{
+ return bcm47xx_board.board;
+}
+EXPORT_SYMBOL(bcm47xx_board_get);
+
+const char *bcm47xx_board_get_name(void)
+{
+ return bcm47xx_board.name;
+}
+EXPORT_SYMBOL(bcm47xx_board_get_name);
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
new file mode 100644
index 00000000000..49a1ce06844
--- /dev/null
+++ b/arch/mips/bcm47xx/buttons.c
@@ -0,0 +1,562 @@
+#include "bcm47xx_private.h"
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/interrupt.h>
+#include <bcm47xx_board.h>
+#include <bcm47xx.h>
+
+/**************************************************
+ * Database
+ **************************************************/
+
+#define BCM47XX_GPIO_KEY(_gpio, _code) \
+ { \
+ .code = _code, \
+ .gpio = _gpio, \
+ .active_low = 1, \
+ }
+
+/* Asus */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_rtn12[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(1, KEY_RESTART),
+ BCM47XX_GPIO_KEY(4, BTN_0), /* Router mode */
+ BCM47XX_GPIO_KEY(5, BTN_1), /* Repeater mode */
+ BCM47XX_GPIO_KEY(6, BTN_2), /* AP mode */
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_rtn16[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(8, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_rtn66u[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(9, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl300g[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl320ge[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl330ge[] __initconst = {
+ BCM47XX_GPIO_KEY(2, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500gd[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500gpv1[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_RESTART),
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500gpv2[] __initconst = {
+ BCM47XX_GPIO_KEY(2, KEY_RESTART),
+ BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500w[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ BCM47XX_GPIO_KEY(7, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl520gc[] __initconst = {
+ BCM47XX_GPIO_KEY(2, KEY_RESTART),
+ BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl520gu[] __initconst = {
+ BCM47XX_GPIO_KEY(2, KEY_RESTART),
+ BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl700ge[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_POWER), /* Hard disk power switch */
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), /* EZSetup */
+ BCM47XX_GPIO_KEY(6, KEY_COPY), /* Copy data from USB to internal disk */
+ BCM47XX_GPIO_KEY(7, KEY_RESTART), /* Hard reset */
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wlhdd[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+/* Huawei */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_huawei_e970[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+/* Belkin */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_belkin_f7d4301[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
+};
+
+/* Buffalo */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_buffalo_whr2_a54g54[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_buffalo_whr_g125[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+ BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode swtich */
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_buffalo_whr_g54s[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+ BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode swtich */
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_buffalo_whr_hp_g54[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+ BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode swtich */
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_buffalo_wzr_g300n[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_buffalo_wzr_rs_g54[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_buffalo_wzr_rs_g54hp[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+};
+
+/* Dell */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_dell_tm2300[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_RESTART),
+};
+
+/* D-Link */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_dlink_dir130[] __initconst = {
+ BCM47XX_GPIO_KEY(3, KEY_RESTART),
+ BCM47XX_GPIO_KEY(7, KEY_UNKNOWN),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_dlink_dir330[] __initconst = {
+ BCM47XX_GPIO_KEY(3, KEY_RESTART),
+ BCM47XX_GPIO_KEY(7, KEY_UNKNOWN),
+};
+
+/* Linksys */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_e1000v1[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_e1000v21[] __initconst = {
+ BCM47XX_GPIO_KEY(9, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(10, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_e2000v1[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(8, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_e3000v1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_e3200v1[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_RESTART),
+ BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_e4200v1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt150nv1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt150nv11[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt160nv1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt160nv3[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt300nv11[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_UNKNOWN),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt310nv1[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ BCM47XX_GPIO_KEY(8, KEY_UNKNOWN),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_WIMAX),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt610nv1[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt610nv2[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+/* Motorola */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_motorola_we800g[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_motorola_wr850gp[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_motorola_wr850gv2v3[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_RESTART),
+};
+
+/* Netgear */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wndr3400v1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+ BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(8, KEY_RFKILL),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wndr3700v3[] __initconst = {
+ BCM47XX_GPIO_KEY(2, KEY_RFKILL),
+ BCM47XX_GPIO_KEY(3, KEY_RESTART),
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wndr4500v1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(5, KEY_RFKILL),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+/* SimpleTech */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_simpletech_simpleshare[] __initconst = {
+ BCM47XX_GPIO_KEY(0, KEY_RESTART),
+};
+
+/**************************************************
+ * Init
+ **************************************************/
+
+static struct gpio_keys_platform_data bcm47xx_button_pdata;
+
+static struct platform_device bcm47xx_buttons_gpio_keys = {
+ .name = "gpio-keys",
+ .dev = {
+ .platform_data = &bcm47xx_button_pdata,
+ }
+};
+
+/* Copy data from __initconst */
+static int __init bcm47xx_buttons_copy(const struct gpio_keys_button *buttons,
+ size_t nbuttons)
+{
+ size_t size = nbuttons * sizeof(*buttons);
+
+ bcm47xx_button_pdata.buttons = kmalloc(size, GFP_KERNEL);
+ if (!bcm47xx_button_pdata.buttons)
+ return -ENOMEM;
+ memcpy(bcm47xx_button_pdata.buttons, buttons, size);
+ bcm47xx_button_pdata.nbuttons = nbuttons;
+
+ return 0;
+}
+
+#define bcm47xx_copy_bdata(dev_buttons) \
+ bcm47xx_buttons_copy(dev_buttons, ARRAY_SIZE(dev_buttons));
+
+int __init bcm47xx_buttons_register(void)
+{
+ enum bcm47xx_board board = bcm47xx_board_get();
+ int err;
+
+ switch (board) {
+ case BCM47XX_BOARD_ASUS_RTN12:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn12);
+ break;
+ case BCM47XX_BOARD_ASUS_RTN16:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn16);
+ break;
+ case BCM47XX_BOARD_ASUS_RTN66U:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn66u);
+ break;
+ case BCM47XX_BOARD_ASUS_WL300G:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl300g);
+ break;
+ case BCM47XX_BOARD_ASUS_WL320GE:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl320ge);
+ break;
+ case BCM47XX_BOARD_ASUS_WL330GE:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500GD:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500GPV1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gpv1);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500GPV2:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gpv2);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500W:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500w);
+ break;
+ case BCM47XX_BOARD_ASUS_WL520GC:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl520gc);
+ break;
+ case BCM47XX_BOARD_ASUS_WL520GU:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl520gu);
+ break;
+ case BCM47XX_BOARD_ASUS_WL700GE:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl700ge);
+ break;
+ case BCM47XX_BOARD_ASUS_WLHDD:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wlhdd);
+ break;
+
+ case BCM47XX_BOARD_BELKIN_F7D3301:
+ case BCM47XX_BOARD_BELKIN_F7D3302:
+ case BCM47XX_BOARD_BELKIN_F7D4301:
+ case BCM47XX_BOARD_BELKIN_F7D4302:
+ case BCM47XX_BOARD_BELKIN_F7D4401:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_belkin_f7d4301);
+ break;
+
+ case BCM47XX_BOARD_BUFFALO_WHR2_A54G54:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr2_a54g54);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WHR_G125:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_g125);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WHR_G54S:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_g54s);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WHR_HP_G54:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_hp_g54);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WZR_G300N:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_g300n);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WZR_RS_G54:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54hp);
+ break;
+
+ case BCM47XX_BOARD_DELL_TM2300:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_dell_tm2300);
+ break;
+
+ case BCM47XX_BOARD_DLINK_DIR130:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_dlink_dir130);
+ break;
+ case BCM47XX_BOARD_DLINK_DIR330:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_dlink_dir330);
+ break;
+
+ case BCM47XX_BOARD_HUAWEI_E970:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_huawei_e970);
+ break;
+
+ case BCM47XX_BOARD_LINKSYS_E1000V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e1000v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E1000V21:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e1000v21);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E2000V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e2000v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E3000V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e3000v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E3200V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e3200v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E4200V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e4200v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT150NV1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt150nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT150NV11:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt150nv11);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT160NV1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt160nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT160NV3:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt160nv3);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT300NV11:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt300nv11);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT310NV1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54gsv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT610NV1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT610NV2:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv2);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRTSL54GS:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
+ break;
+
+ case BCM47XX_BOARD_MOTOROLA_WE800G:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
+ break;
+ case BCM47XX_BOARD_MOTOROLA_WR850GP:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gp);
+ break;
+ case BCM47XX_BOARD_MOTOROLA_WR850GV2V3:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gv2v3);
+ break;
+
+ case BCM47XX_BOARD_NETGEAR_WNDR3400V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400v1);
+ break;
+ case BCM47XX_BOARD_NETGEAR_WNDR3700V3:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3700v3);
+ break;
+ case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
+ break;
+ case BCM47XX_BOARD_NETGEAR_WNR834BV2:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
+ break;
+
+ case BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_simpletech_simpleshare);
+ break;
+
+ default:
+ pr_debug("No buttons configuration found for this device\n");
+ return -ENOTSUPP;
+ }
+
+ if (err)
+ return -ENOMEM;
+
+ err = platform_device_register(&bcm47xx_buttons_gpio_keys);
+ if (err) {
+ pr_err("Failed to register platform device: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
diff --git a/arch/mips/bcm47xx/irq.c b/arch/mips/bcm47xx/irq.c
index 8cf3833b2d2..e0585b76ec1 100644
--- a/arch/mips/bcm47xx/irq.c
+++ b/arch/mips/bcm47xx/irq.c
@@ -25,10 +25,11 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <asm/setup.h>
#include <asm/irq_cpu.h>
#include <bcm47xx.h>
-void plat_irq_dispatch(void)
+asmlinkage void plat_irq_dispatch(void)
{
u32 cause;
@@ -50,6 +51,18 @@ void plat_irq_dispatch(void)
do_IRQ(6);
}
+#define DEFINE_HWx_IRQDISPATCH(x) \
+ static void bcm47xx_hw ## x ## _irqdispatch(void) \
+ { \
+ do_IRQ(x); \
+ }
+DEFINE_HWx_IRQDISPATCH(2)
+DEFINE_HWx_IRQDISPATCH(3)
+DEFINE_HWx_IRQDISPATCH(4)
+DEFINE_HWx_IRQDISPATCH(5)
+DEFINE_HWx_IRQDISPATCH(6)
+DEFINE_HWx_IRQDISPATCH(7)
+
void __init arch_init_irq(void)
{
#ifdef CONFIG_BCM47XX_BCMA
@@ -64,4 +77,14 @@ void __init arch_init_irq(void)
}
#endif
mips_cpu_irq_init();
+
+ if (cpu_has_vint) {
+ pr_info("Setting up vectored interrupts\n");
+ set_vi_handler(2, bcm47xx_hw2_irqdispatch);
+ set_vi_handler(3, bcm47xx_hw3_irqdispatch);
+ set_vi_handler(4, bcm47xx_hw4_irqdispatch);
+ set_vi_handler(5, bcm47xx_hw5_irqdispatch);
+ set_vi_handler(6, bcm47xx_hw6_irqdispatch);
+ set_vi_handler(7, bcm47xx_hw7_irqdispatch);
+ }
}
diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c
new file mode 100644
index 00000000000..adcb547a91c
--- /dev/null
+++ b/arch/mips/bcm47xx/leds.c
@@ -0,0 +1,591 @@
+#include "bcm47xx_private.h"
+
+#include <linux/leds.h>
+#include <bcm47xx_board.h>
+
+/**************************************************
+ * Database
+ **************************************************/
+
+#define BCM47XX_GPIO_LED(_gpio, _color, _function, _active_low, \
+ _default_state) \
+ { \
+ .name = "bcm47xx:" _color ":" _function, \
+ .gpio = _gpio, \
+ .active_low = _active_low, \
+ .default_state = _default_state, \
+ }
+
+#define BCM47XX_GPIO_LED_TRIGGER(_gpio, _color, _function, _active_low, \
+ _default_trigger) \
+ { \
+ .name = "bcm47xx:" _color ":" _function, \
+ .gpio = _gpio, \
+ .active_low = _active_low, \
+ .default_state = LEDS_GPIO_DEFSTATE_OFF, \
+ .default_trigger = _default_trigger, \
+ }
+
+/* Asus */
+
+static const struct gpio_led
+bcm47xx_leds_asus_rtn12[] __initconst = {
+ BCM47XX_GPIO_LED(2, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_rtn16[] __initconst = {
+ BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_rtn66u[] __initconst = {
+ BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl300g[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl320ge[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(11, "unk", "link", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl330ge[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl500gd[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl500gpv1[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl500gpv2[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(1, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl500w[] __initconst = {
+ BCM47XX_GPIO_LED(5, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl520gc[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(1, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl520gu[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(1, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wl700ge[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), /* Labeled "READY" (there is no "power" LED). Originally ON, flashing on USB activity. */
+};
+
+static const struct gpio_led
+bcm47xx_leds_asus_wlhdd[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(2, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Belkin */
+
+static const struct gpio_led
+bcm47xx_leds_belkin_f7d4301[] __initconst = {
+ BCM47XX_GPIO_LED(10, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(11, "amber", "power", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(12, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(13, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(14, "unk", "usb0", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(15, "unk", "usb1", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Buffalo */
+
+static const struct gpio_led
+bcm47xx_leds_buffalo_whr2_a54g54[] __initconst = {
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_buffalo_whr_g125[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "unk", "internal", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_buffalo_whr_g54s[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "unk", "internal", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_buffalo_whr_hp_g54[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "unk", "internal", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_buffalo_wzr_g300n[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_buffalo_wzr_rs_g54[] __initconst = {
+ BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "vpn", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_buffalo_wzr_rs_g54hp[] __initconst = {
+ BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "vpn", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Dell */
+
+static const struct gpio_led
+bcm47xx_leds_dell_tm2300[] __initconst = {
+ BCM47XX_GPIO_LED(6, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+/* D-Link */
+
+static const struct gpio_led
+bcm47xx_leds_dlink_dir130[] __initconst = {
+ BCM47XX_GPIO_LED_TRIGGER(0, "green", "status", 1, "timer"), /* Originally blinking when device is ready, separated from "power" LED */
+ BCM47XX_GPIO_LED(6, "blue", "unk", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_dlink_dir330[] __initconst = {
+ BCM47XX_GPIO_LED_TRIGGER(0, "green", "status", 1, "timer"), /* Originally blinking when device is ready, separated from "power" LED */
+ BCM47XX_GPIO_LED(4, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "blue", "unk", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Huawei */
+
+static const struct gpio_led
+bcm47xx_leds_huawei_e970[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Linksys */
+
+static const struct gpio_led
+bcm47xx_leds_linksys_e1000v1[] __initconst = {
+ BCM47XX_GPIO_LED(0, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(2, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(4, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_e1000v21[] __initconst = {
+ BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_e2000v1[] __initconst = {
+ BCM47XX_GPIO_LED(1, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(4, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_e3000v1[] __initconst = {
+ BCM47XX_GPIO_LED(0, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "unk", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_e3200v1[] __initconst = {
+ BCM47XX_GPIO_LED(3, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_e4200v1[] __initconst = {
+ BCM47XX_GPIO_LED(5, "white", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt150nv1[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt150nv11[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt160nv1[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt160nv3[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(2, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(4, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt300nv11[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt310nv1[] __initconst = {
+ BCM47XX_GPIO_LED(1, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(9, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54gsv1[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g3gv2[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(2, "green", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "blue", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(9, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt610nv2[] __initconst = {
+ BCM47XX_GPIO_LED(0, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "unk", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Motorola */
+
+static const struct gpio_led
+bcm47xx_leds_motorola_we800g[] __initconst = {
+ BCM47XX_GPIO_LED(1, "amber", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "unk", "unk", 1, LEDS_GPIO_DEFSTATE_OFF), /* There are only 3 LEDs: Power, Wireless and Device (ethernet) */
+ BCM47XX_GPIO_LED(4, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
+bcm47xx_leds_motorola_wr850gp[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(6, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_motorola_wr850gv2v3[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Netgear */
+
+static const struct gpio_led
+bcm47xx_leds_netgear_wndr3400v1[] __initconst = {
+ BCM47XX_GPIO_LED(2, "green", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_netgear_wndr4500v1[] __initconst = {
+ BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "power", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(8, "green", "usb1", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(9, "green", "2ghz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(11, "blue", "5ghz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(14, "green", "usb2", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_netgear_wnr834bv2[] __initconst = {
+ BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "unk", "connected", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Siemens */
+static const struct gpio_led
+bcm47xx_leds_siemens_se505v2[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+/* SimpleTech */
+
+static const struct gpio_led
+bcm47xx_leds_simpletech_simpleshare[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "status", 1, LEDS_GPIO_DEFSTATE_OFF), /* "Ready" LED */
+};
+
+/**************************************************
+ * Init
+ **************************************************/
+
+static struct gpio_led_platform_data bcm47xx_leds_pdata;
+
+#define bcm47xx_set_pdata(dev_leds) do { \
+ bcm47xx_leds_pdata.leds = dev_leds; \
+ bcm47xx_leds_pdata.num_leds = ARRAY_SIZE(dev_leds); \
+} while (0)
+
+void __init bcm47xx_leds_register(void)
+{
+ enum bcm47xx_board board = bcm47xx_board_get();
+
+ switch (board) {
+ case BCM47XX_BOARD_ASUS_RTN12:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12);
+ break;
+ case BCM47XX_BOARD_ASUS_RTN16:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16);
+ break;
+ case BCM47XX_BOARD_ASUS_RTN66U:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn66u);
+ break;
+ case BCM47XX_BOARD_ASUS_WL300G:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl300g);
+ break;
+ case BCM47XX_BOARD_ASUS_WL320GE:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl320ge);
+ break;
+ case BCM47XX_BOARD_ASUS_WL330GE:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500GD:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500GPV1:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gpv1);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500GPV2:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gpv2);
+ break;
+ case BCM47XX_BOARD_ASUS_WL500W:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500w);
+ break;
+ case BCM47XX_BOARD_ASUS_WL520GC:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl520gc);
+ break;
+ case BCM47XX_BOARD_ASUS_WL520GU:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl520gu);
+ break;
+ case BCM47XX_BOARD_ASUS_WL700GE:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl700ge);
+ break;
+ case BCM47XX_BOARD_ASUS_WLHDD:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wlhdd);
+ break;
+
+ case BCM47XX_BOARD_BELKIN_F7D3301:
+ case BCM47XX_BOARD_BELKIN_F7D3302:
+ case BCM47XX_BOARD_BELKIN_F7D4301:
+ case BCM47XX_BOARD_BELKIN_F7D4302:
+ case BCM47XX_BOARD_BELKIN_F7D4401:
+ bcm47xx_set_pdata(bcm47xx_leds_belkin_f7d4301);
+ break;
+
+ case BCM47XX_BOARD_BUFFALO_WHR2_A54G54:
+ bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr2_a54g54);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WHR_G125:
+ bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr_g125);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WHR_G54S:
+ bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr_g54s);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WHR_HP_G54:
+ bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr_hp_g54);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WZR_G300N:
+ bcm47xx_set_pdata(bcm47xx_leds_buffalo_wzr_g300n);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WZR_RS_G54:
+ bcm47xx_set_pdata(bcm47xx_leds_buffalo_wzr_rs_g54);
+ break;
+ case BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP:
+ bcm47xx_set_pdata(bcm47xx_leds_buffalo_wzr_rs_g54hp);
+ break;
+
+ case BCM47XX_BOARD_DELL_TM2300:
+ bcm47xx_set_pdata(bcm47xx_leds_dell_tm2300);
+ break;
+
+ case BCM47XX_BOARD_DLINK_DIR130:
+ bcm47xx_set_pdata(bcm47xx_leds_dlink_dir130);
+ break;
+ case BCM47XX_BOARD_DLINK_DIR330:
+ bcm47xx_set_pdata(bcm47xx_leds_dlink_dir330);
+ break;
+
+ case BCM47XX_BOARD_HUAWEI_E970:
+ bcm47xx_set_pdata(bcm47xx_leds_huawei_e970);
+ break;
+
+ case BCM47XX_BOARD_LINKSYS_E1000V1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_e1000v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E1000V21:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_e1000v21);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E2000V1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_e2000v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E3000V1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_e3000v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E3200V1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_e3200v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_E4200V1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_e4200v1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT150NV1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt150nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT150NV11:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt150nv11);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT160NV1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt160nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT160NV3:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt160nv3);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT300NV11:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt300nv11);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT310NV1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54gsv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT610NV1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT610NV2:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv2);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRTSL54GS:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
+ break;
+
+ case BCM47XX_BOARD_MOTOROLA_WE800G:
+ bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);
+ break;
+ case BCM47XX_BOARD_MOTOROLA_WR850GP:
+ bcm47xx_set_pdata(bcm47xx_leds_motorola_wr850gp);
+ break;
+ case BCM47XX_BOARD_MOTOROLA_WR850GV2V3:
+ bcm47xx_set_pdata(bcm47xx_leds_motorola_wr850gv2v3);
+ break;
+
+ case BCM47XX_BOARD_NETGEAR_WNDR3400V1:
+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr3400v1);
+ break;
+ case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
+ break;
+ case BCM47XX_BOARD_NETGEAR_WNR834BV2:
+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
+ break;
+
+ case BCM47XX_BOARD_SIEMENS_SE505V2:
+ bcm47xx_set_pdata(bcm47xx_leds_siemens_se505v2);
+ break;
+
+ case BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE:
+ bcm47xx_set_pdata(bcm47xx_leds_simpletech_simpleshare);
+ break;
+
+ default:
+ pr_debug("No LEDs configuration found for this device\n");
+ return;
+ }
+
+ gpio_led_register_device(-1, &bcm47xx_leds_pdata);
+}
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index cc40b74940f..2bed73a684a 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -11,7 +11,6 @@
* option) any later version.
*/
-#include <linux/init.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/ssb/ssb.h>
@@ -22,11 +21,11 @@
#include <asm/mach-bcm47xx/bcm47xx.h>
static char nvram_buf[NVRAM_SPACE];
+static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
static u32 find_nvram_size(u32 end)
{
struct nvram_header *header;
- u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
int i;
for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
@@ -190,3 +189,23 @@ int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
return -ENOENT;
}
EXPORT_SYMBOL(bcm47xx_nvram_getenv);
+
+int bcm47xx_nvram_gpio_pin(const char *name)
+{
+ int i, err;
+ char nvram_var[10];
+ char buf[30];
+
+ for (i = 0; i < 32; 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/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index 8c155afb129..1a03a2f4349 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -28,101 +28,27 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
+#include <linux/ssb/ssb_driver_chipcommon.h>
+#include <linux/ssb/ssb_regs.h>
#include <linux/smp.h>
#include <asm/bootinfo.h>
-#include <asm/fw/cfe/cfe_api.h>
-#include <asm/fw/cfe/cfe_error.h>
+#include <bcm47xx.h>
+#include <bcm47xx_board.h>
-static int cfe_cons_handle;
-const char *get_system_type(void)
-{
- return "Broadcom BCM47XX";
-}
-
-void prom_putchar(char c)
-{
- while (cfe_write(cfe_cons_handle, &c, 1) == 0)
- ;
-}
-
-static __init void prom_init_cfe(void)
-{
- uint32_t cfe_ept;
- uint32_t cfe_handle;
- uint32_t cfe_eptseal;
- int argc = fw_arg0;
- char **envp = (char **) fw_arg2;
- int *prom_vec = (int *) fw_arg3;
-
- /*
- * Check if a loader was used; if NOT, the 4 arguments are
- * what CFE gives us (handle, 0, EPT and EPTSEAL)
- */
- if (argc < 0) {
- cfe_handle = (uint32_t)argc;
- cfe_ept = (uint32_t)envp;
- cfe_eptseal = (uint32_t)prom_vec;
- } else {
- if ((int)prom_vec < 0) {
- /*
- * Old loader; all it gives us is the handle,
- * so use the "known" entrypoint and assume
- * the seal.
- */
- cfe_handle = (uint32_t)prom_vec;
- cfe_ept = 0xBFC00500;
- cfe_eptseal = CFE_EPTSEAL;
- } else {
- /*
- * Newer loaders bundle the handle/ept/eptseal
- * Note: prom_vec is in the loader's useg
- * which is still alive in the TLB.
- */
- cfe_handle = prom_vec[0];
- cfe_ept = prom_vec[2];
- cfe_eptseal = prom_vec[3];
- }
- }
-
- if (cfe_eptseal != CFE_EPTSEAL) {
- /* too early for panic to do any good */
- printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
- while (1) ;
- }
+static char bcm47xx_system_type[20] = "Broadcom BCM47XX";
- cfe_init(cfe_handle, cfe_ept);
-}
-
-static __init void prom_init_console(void)
+const char *get_system_type(void)
{
- /* Initialize CFE console */
- cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
+ return bcm47xx_system_type;
}
-static __init void prom_init_cmdline(void)
+__init void bcm47xx_set_system_type(u16 chip_id)
{
- static char buf[COMMAND_LINE_SIZE] __initdata;
-
- /* Get the kernel command line from CFE */
- if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
- buf[COMMAND_LINE_SIZE - 1] = 0;
- strcpy(arcs_cmdline, buf);
- }
-
- /* Force a console handover by adding a console= argument if needed,
- * as CFE is not available anymore later in the boot process. */
- if ((strstr(arcs_cmdline, "console=")) == NULL) {
- /* Try to read the default serial port used by CFE */
- if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
- || (strncmp("uart", buf, 4)))
- /* Default to uart0 */
- strcpy(buf, "uart0");
-
- /* Compute the new command line */
- snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
- arcs_cmdline, buf[4]);
- }
+ snprintf(bcm47xx_system_type, sizeof(bcm47xx_system_type),
+ (chip_id > 0x9999) ? "Broadcom BCM%d" :
+ "Broadcom BCM%04X",
+ chip_id);
}
static __init void prom_init_mem(void)
@@ -143,15 +69,18 @@ static __init void prom_init_mem(void)
* BCM47XX uses 128MB for addressing the ram, if the system contains
* less that that amount of ram it remaps the ram more often into the
* available space.
- * Accessing memory after 128MB will cause an exception.
- * max contains the biggest possible address supported by the platform.
- * If the method wants to try something above we assume 128MB ram.
*/
- off = (unsigned long)prom_init;
- max = off | ((128 << 20) - 1);
- for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
- if ((off + mem) > max) {
- mem = (128 << 20);
+
+ /* Physical address, without mapping to any kernel segment */
+ off = CPHYSADDR((unsigned long)prom_init);
+
+ /* Accessing memory after 128 MiB will cause an exception */
+ max = 128 << 20;
+
+ for (mem = 1 << 20; mem < max; mem += 1 << 20) {
+ /* Loop condition may be not enough, off may be over 1 MiB */
+ if (off + mem >= max) {
+ mem = max;
printk(KERN_DEBUG "assume 128MB RAM\n");
break;
}
@@ -170,12 +99,16 @@ static __init void prom_init_mem(void)
add_memory_region(0, mem, BOOT_MEM_RAM);
}
+/*
+ * This is the first serial on the chip common core, it is at this position
+ * for sb (ssb) and ai (bcma) bus.
+ */
+#define BCM47XX_SERIAL_ADDR (SSB_ENUM_BASE + SSB_CHIPCO_UART0_DATA)
+
void __init prom_init(void)
{
- prom_init_cfe();
- prom_init_console();
- prom_init_cmdline();
prom_init_mem();
+ setup_8250_early_printk_port(CKSEG1ADDR(BCM47XX_SERIAL_ADDR), 0, 0);
}
void __init prom_free_prom_memory(void)
diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c
index b8ef965705c..2f5bbd68e9a 100644
--- a/arch/mips/bcm47xx/serial.c
+++ b/arch/mips/bcm47xx/serial.c
@@ -31,7 +31,8 @@ static int __init uart8250_init_ssb(void)
memset(&uart8250_data, 0, sizeof(uart8250_data));
- for (i = 0; i < mcore->nr_serial_ports; i++) {
+ for (i = 0; i < mcore->nr_serial_ports &&
+ i < ARRAY_SIZE(uart8250_data) - 1; i++) {
struct plat_serial8250_port *p = &(uart8250_data[i]);
struct ssb_serial_port *ssb_port = &(mcore->serial_ports[i]);
@@ -55,7 +56,8 @@ static int __init uart8250_init_bcma(void)
memset(&uart8250_data, 0, sizeof(uart8250_data));
- for (i = 0; i < cc->nr_serial_ports; i++) {
+ for (i = 0; i < cc->nr_serial_ports &&
+ i < ARRAY_SIZE(uart8250_data) - 1; i++) {
struct plat_serial8250_port *p = &(uart8250_data[i]);
struct bcma_serial_port *bcma_port;
bcma_port = &(cc->serial_ports[i]);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index b2246cd9ca1..63a4b0e915d 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -26,16 +26,24 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "bcm47xx_private.h"
+
#include <linux/export.h>
#include <linux/types.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma_soc.h>
#include <asm/bootinfo.h>
+#include <asm/idle.h>
+#include <asm/prom.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <bcm47xx.h>
#include <bcm47xx_nvram.h>
+#include <bcm47xx_board.h>
union bcm47xx_bus bcm47xx_bus;
EXPORT_SYMBOL(bcm47xx_bus);
@@ -204,24 +212,59 @@ void __init plat_mem_setup(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
- if (c->cputype == CPU_74K) {
+ if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K)) {
printk(KERN_INFO "bcm47xx: using bcma bus\n");
#ifdef CONFIG_BCM47XX_BCMA
bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
bcm47xx_register_bcma();
+ bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
#endif
} else {
printk(KERN_INFO "bcm47xx: using ssb bus\n");
#ifdef CONFIG_BCM47XX_SSB
bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
bcm47xx_register_ssb();
+ bcm47xx_set_system_type(bcm47xx_bus.ssb.chip_id);
#endif
}
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;
+ bcm47xx_board_detect();
+ mips_set_machine_name(bcm47xx_board_get_name());
+}
+
+static int __init bcm47xx_cpu_fixes(void)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ /* Nothing to do */
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ /* The BCM4706 has a problem with the CPU wait instruction.
+ * When r4k_wait or r4k_wait_irqoff is used will just hang and
+ * not return from a msleep(). Removing the cpu_wait
+ * functionality is a workaround for this problem. The BCM4716
+ * does not have this problem.
+ */
+ if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
+ cpu_wait = NULL;
+ break;
+#endif
+ }
+ return 0;
}
+arch_initcall(bcm47xx_cpu_fixes);
+
+static struct fixed_phy_status bcm47xx_fixed_phy_status __initdata = {
+ .link = 1,
+ .speed = SPEED_100,
+ .duplex = DUPLEX_FULL,
+};
static int __init bcm47xx_register_bus_complete(void)
{
@@ -237,6 +280,11 @@ static int __init bcm47xx_register_bus_complete(void)
break;
#endif
}
+ bcm47xx_buttons_register();
+ bcm47xx_leds_register();
+ bcm47xx_workarounds();
+
+ fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
return 0;
}
device_initcall(bcm47xx_register_bus_complete);
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
index ad03c931b90..da4cdb16844 100644
--- a/arch/mips/bcm47xx/sprom.c
+++ b/arch/mips/bcm47xx/sprom.c
@@ -135,7 +135,7 @@ static void nvram_read_leddc(const char *prefix, const char *name,
}
static void nvram_read_macaddr(const char *prefix, const char *name,
- u8 (*val)[6], bool fallback)
+ u8 val[6], bool fallback)
{
char buf[100];
int err;
@@ -144,11 +144,11 @@ static void nvram_read_macaddr(const char *prefix, const char *name,
if (err < 0)
return;
- bcm47xx_nvram_parse_macaddr(buf, *val);
+ bcm47xx_nvram_parse_macaddr(buf, val);
}
static void nvram_read_alpha2(const char *prefix, const char *name,
- char (*val)[2], bool fallback)
+ char val[2], bool fallback)
{
char buf[10];
int err;
@@ -162,12 +162,13 @@ static void nvram_read_alpha2(const char *prefix, const char *name,
pr_warn("alpha2 is too long %s\n", buf);
return;
}
- memcpy(val, buf, sizeof(val));
+ memcpy(val, buf, 2);
}
static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
const char *prefix, bool fallback)
{
+ nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback);
nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback);
nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback);
nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback);
@@ -180,7 +181,7 @@ static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
fallback);
nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0,
fallback);
- nvram_read_alpha2(prefix, "ccode", &sprom->alpha2, fallback);
+ nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback);
}
static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
@@ -633,20 +634,20 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
const char *prefix, bool fallback)
{
- nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac, fallback);
+ nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback);
nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
fallback);
nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0,
fallback);
- nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac, fallback);
+ nvram_read_macaddr(prefix, "et1macaddr", sprom->et1mac, fallback);
nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0,
fallback);
nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
fallback);
- nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac, fallback);
- nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac, fallback);
+ nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
+ nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
}
static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c
index 536374dcba7..2c85d9254b5 100644
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -27,10 +27,16 @@
#include <linux/ssb/ssb.h>
#include <asm/time.h>
#include <bcm47xx.h>
+#include <bcm47xx_nvram.h>
+#include <bcm47xx_board.h>
void __init plat_time_init(void)
{
unsigned long hz = 0;
+ u16 chip_id = 0;
+ char buf[10];
+ int len;
+ enum bcm47xx_board board = bcm47xx_board_get();
/*
* Use deterministic values for initial counter interrupt
@@ -43,15 +49,32 @@ void __init plat_time_init(void)
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+ chip_id = bcm47xx_bus.ssb.chip_id;
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
+ chip_id = bcm47xx_bus.bcma.bus.chipinfo.id;
break;
#endif
}
+ if (chip_id == 0x5354) {
+ len = bcm47xx_nvram_getenv("clkfreq", buf, sizeof(buf));
+ if (len >= 0 && !strncmp(buf, "200", 4))
+ hz = 100000000;
+ }
+
+ switch (board) {
+ case BCM47XX_BOARD_ASUS_WL520GC:
+ case BCM47XX_BOARD_ASUS_WL520GU:
+ hz = 100000000;
+ break;
+ default:
+ break;
+ }
+
if (!hz)
hz = 100000000;
diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c
deleted file mode 100644
index c63a4c287b5..00000000000
--- a/arch/mips/bcm47xx/wgt634u.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/leds.h>
-#include <linux/mtd/physmap.h>
-#include <linux/ssb/ssb.h>
-#include <linux/ssb/ssb_embedded.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/gpio.h>
-#include <asm/mach-bcm47xx/bcm47xx.h>
-
-/* GPIO definitions for the WGT634U */
-#define WGT634U_GPIO_LED 3
-#define WGT634U_GPIO_RESET 2
-#define WGT634U_GPIO_TP1 7
-#define WGT634U_GPIO_TP2 6
-#define WGT634U_GPIO_TP3 5
-#define WGT634U_GPIO_TP4 4
-#define WGT634U_GPIO_TP5 1
-
-static struct gpio_led wgt634u_leds[] = {
- {
- .name = "power",
- .gpio = WGT634U_GPIO_LED,
- .active_low = 1,
- .default_trigger = "heartbeat",
- },
-};
-
-static struct gpio_led_platform_data wgt634u_led_data = {
- .num_leds = ARRAY_SIZE(wgt634u_leds),
- .leds = wgt634u_leds,
-};
-
-static struct platform_device wgt634u_gpio_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &wgt634u_led_data,
- }
-};
-
-
-/* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U
- firmware. */
-static struct mtd_partition wgt634u_partitions[] = {
- {
- .name = "cfe",
- .offset = 0,
- .size = 0x60000, /* 384k */
- .mask_flags = MTD_WRITEABLE /* force read-only */
- },
- {
- .name = "config",
- .offset = 0x60000,
- .size = 0x20000 /* 128k */
- },
- {
- .name = "linux",
- .offset = 0x80000,
- .size = 0x140000 /* 1280k */
- },
- {
- .name = "jffs",
- .offset = 0x1c0000,
- .size = 0x620000 /* 6272k */
- },
- {
- .name = "nvram",
- .offset = 0x7e0000,
- .size = 0x20000 /* 128k */
- },
-};
-
-static struct physmap_flash_data wgt634u_flash_data = {
- .parts = wgt634u_partitions,
- .nr_parts = ARRAY_SIZE(wgt634u_partitions)
-};
-
-static struct resource wgt634u_flash_resource = {
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device wgt634u_flash = {
- .name = "physmap-flash",
- .id = 0,
- .dev = { .platform_data = &wgt634u_flash_data, },
- .resource = &wgt634u_flash_resource,
- .num_resources = 1,
-};
-
-/* Platform devices */
-static struct platform_device *wgt634u_devices[] __initdata = {
- &wgt634u_flash,
- &wgt634u_gpio_leds,
-};
-
-static irqreturn_t gpio_interrupt(int irq, void *ignored)
-{
- int state;
-
- /* Interrupts are shared, check if the current one is
- a GPIO interrupt. */
- if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
- SSB_CHIPCO_IRQ_GPIO))
- return IRQ_NONE;
-
- state = gpio_get_value(WGT634U_GPIO_RESET);
-
- /* Interrupt are level triggered, revert the interrupt polarity
- to clear the interrupt. */
- ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << WGT634U_GPIO_RESET,
- state ? 1 << WGT634U_GPIO_RESET : 0);
-
- if (!state) {
- printk(KERN_INFO "Reset button pressed");
- ctrl_alt_del();
- }
-
- return IRQ_HANDLED;
-}
-
-static int __init wgt634u_init(void)
-{
- /* There is no easy way to detect that we are running on a WGT634U
- * machine. Use the MAC address as an heuristic. Netgear Inc. has
- * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
- */
- u8 *et0mac;
-
- if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
- return -ENODEV;
-
- et0mac = bcm47xx_bus.ssb.sprom.et0mac;
-
- if (et0mac[0] == 0x00 &&
- ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
- (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
- struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
-
- printk(KERN_INFO "WGT634U machine detected.\n");
-
- if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
- gpio_interrupt, IRQF_SHARED,
- "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
- gpio_direction_input(WGT634U_GPIO_RESET);
- ssb_gpio_intmask(&bcm47xx_bus.ssb,
- 1 << WGT634U_GPIO_RESET,
- 1 << WGT634U_GPIO_RESET);
- ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
- SSB_CHIPCO_IRQ_GPIO,
- SSB_CHIPCO_IRQ_GPIO);
- }
-
- wgt634u_flash_data.width = mcore->pflash.buswidth;
- wgt634u_flash_resource.start = mcore->pflash.window;
- wgt634u_flash_resource.end = mcore->pflash.window
- + mcore->pflash.window_size
- - 1;
- return platform_add_devices(wgt634u_devices,
- ARRAY_SIZE(wgt634u_devices));
- } else
- return -ENODEV;
-}
-
-module_init(wgt634u_init);
diff --git a/arch/mips/bcm47xx/workarounds.c b/arch/mips/bcm47xx/workarounds.c
new file mode 100644
index 00000000000..e81ce462307
--- /dev/null
+++ b/arch/mips/bcm47xx/workarounds.c
@@ -0,0 +1,31 @@
+#include "bcm47xx_private.h"
+
+#include <linux/gpio.h>
+#include <bcm47xx_board.h>
+#include <bcm47xx.h>
+
+static void __init bcm47xx_workarounds_netgear_wnr3500l(void)
+{
+ const int usb_power = 12;
+ int err;
+
+ err = gpio_request_one(usb_power, GPIOF_OUT_INIT_HIGH, "usb_power");
+ if (err)
+ pr_err("Failed to request USB power gpio: %d\n", err);
+ else
+ gpio_free(usb_power);
+}
+
+void __init bcm47xx_workarounds(void)
+{
+ enum bcm47xx_board board = bcm47xx_board_get();
+
+ switch (board) {
+ case BCM47XX_BOARD_NETGEAR_WNR3500L:
+ bcm47xx_workarounds_netgear_wnr3500l();
+ break;
+ default:
+ /* No workaround(s) needed */
+ break;
+ }
+}
diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig
index b78306ce56c..a057fdf111c 100644
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -3,33 +3,41 @@ menu "CPU support"
config BCM63XX_CPU_3368
bool "support 3368 CPU"
+ select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
config BCM63XX_CPU_6328
bool "support 6328 CPU"
+ select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
config BCM63XX_CPU_6338
bool "support 6338 CPU"
+ select SYS_HAS_CPU_BMIPS32_3300
select HW_HAS_PCI
config BCM63XX_CPU_6345
bool "support 6345 CPU"
+ select SYS_HAS_CPU_BMIPS32_3300
config BCM63XX_CPU_6348
bool "support 6348 CPU"
+ select SYS_HAS_CPU_BMIPS32_3300
select HW_HAS_PCI
config BCM63XX_CPU_6358
bool "support 6358 CPU"
+ select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
config BCM63XX_CPU_6362
bool "support 6362 CPU"
+ select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
config BCM63XX_CPU_6368
bool "support 6368 CPU"
+ select SYS_HAS_CPU_BMIPS4350
select HW_HAS_PCI
endmenu
diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile
index ac2807397c1..9019f54aee6 100644
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,7 +1,7 @@
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
- dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-wdt.o \
- dev-usb-usbd.o
+ dev-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \
+ dev-wdt.o dev-usb-usbd.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index 5b974eb125f..33727e7f0c7 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -23,6 +23,7 @@
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_dsp.h>
#include <bcm63xx_dev_flash.h>
+#include <bcm63xx_dev_hsspi.h>
#include <bcm63xx_dev_pcmcia.h>
#include <bcm63xx_dev_spi.h>
#include <bcm63xx_dev_usb_usbd.h>
@@ -915,6 +916,8 @@ int __init board_register_devices(void)
bcm63xx_spi_register();
+ bcm63xx_hsspi_register();
+
bcm63xx_flash_register();
bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c
index 43da4ae04cc..63756528473 100644
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -226,6 +226,28 @@ static struct clk clk_spi = {
};
/*
+ * HSSPI clock
+ */
+static void hsspi_set(struct clk *clk, int enable)
+{
+ u32 mask;
+
+ if (BCMCPU_IS_6328())
+ mask = CKCTL_6328_HSSPI_EN;
+ else if (BCMCPU_IS_6362())
+ mask = CKCTL_6362_HSSPI_EN;
+ else
+ return;
+
+ bcm_hwclock_set(mask, enable);
+}
+
+static struct clk clk_hsspi = {
+ .set = hsspi_set,
+};
+
+
+/*
* XTM clock
*/
static void xtm_set(struct clk *clk, int enable)
@@ -346,6 +368,8 @@ struct clk *clk_get(struct device *dev, const char *id)
return &clk_usbd;
if (!strcmp(id, "spi"))
return &clk_spi;
+ if (!strcmp(id, "hsspi"))
+ return &clk_hsspi;
if (!strcmp(id, "xtm"))
return &clk_xtm;
if (!strcmp(id, "periph"))
@@ -366,3 +390,21 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);
+
+#define HSSPI_PLL_HZ_6328 133333333
+#define HSSPI_PLL_HZ_6362 400000000
+
+static int __init bcm63xx_clk_init(void)
+{
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM6328_CPU_ID:
+ clk_hsspi.rate = HSSPI_PLL_HZ_6328;
+ break;
+ case BCM6362_CPU_ID:
+ clk_hsspi.rate = HSSPI_PLL_HZ_6362;
+ break;
+ }
+
+ return 0;
+}
+arch_initcall(bcm63xx_clk_init);
diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c
index 7e17374a9ae..fd4e76c00a4 100644
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -123,7 +123,9 @@ unsigned int bcm63xx_get_memory_size(void)
static unsigned int detect_cpu_clock(void)
{
- switch (bcm63xx_get_cpu_id()) {
+ u16 cpu_id = bcm63xx_get_cpu_id();
+
+ switch (cpu_id) {
case BCM3368_CPU_ID:
return 300000000;
@@ -249,7 +251,7 @@ static unsigned int detect_cpu_clock(void)
}
default:
- BUG();
+ panic("Failed to detect clock for CPU with id=%04X\n", cpu_id);
}
}
@@ -297,23 +299,22 @@ static unsigned int detect_memory_size(void)
void __init bcm63xx_cpu_init(void)
{
unsigned int tmp;
- struct cpuinfo_mips *c = &current_cpu_data;
unsigned int cpu = smp_processor_id();
u32 chipid_reg;
/* soc registers location depends on cpu type */
chipid_reg = 0;
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_BMIPS3300:
- if ((read_c0_prid() & 0xff00) != PRID_IMP_BMIPS3300_ALT)
+ if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT)
__cpu_name[cpu] = "Broadcom BCM6338";
/* fall-through */
case CPU_BMIPS32:
chipid_reg = BCM_6345_PERF_BASE;
break;
case CPU_BMIPS4350:
- switch ((read_c0_prid() & 0xff)) {
+ switch ((read_c0_prid() & PRID_REV_MASK)) {
case 0x04:
chipid_reg = BCM_3368_PERF_BASE;
break;
diff --git a/arch/mips/bcm63xx/dev-hsspi.c b/arch/mips/bcm63xx/dev-hsspi.c
new file mode 100644
index 00000000000..696abc48e3c
--- /dev/null
+++ b/arch/mips/bcm63xx/dev-hsspi.c
@@ -0,0 +1,47 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_dev_hsspi.h>
+#include <bcm63xx_regs.h>
+
+static struct resource spi_resources[] = {
+ {
+ .start = -1, /* filled at runtime */
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = -1, /* filled at runtime */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bcm63xx_hsspi_device = {
+ .name = "bcm63xx-hsspi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(spi_resources),
+ .resource = spi_resources,
+};
+
+int __init bcm63xx_hsspi_register(void)
+{
+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362())
+ return -ENODEV;
+
+ spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
+ spi_resources[0].end = spi_resources[0].start;
+ spi_resources[0].end += RSET_HSSPI_SIZE - 1;
+ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI);
+
+ return platform_device_register(&bcm63xx_hsspi_device);
+}
diff --git a/arch/mips/bcm63xx/early_printk.c b/arch/mips/bcm63xx/early_printk.c
index aa8f7f9cc7a..6092226a6d7 100644
--- a/arch/mips/bcm63xx/early_printk.c
+++ b/arch/mips/bcm63xx/early_printk.c
@@ -6,9 +6,8 @@
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
*/
-#include <linux/init.h>
#include <bcm63xx_io.h>
-#include <bcm63xx_regs.h>
+#include <linux/serial_bcm63xx.h>
static void wait_xfered(void)
{
diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c
index 8ac4e095e68..e1f27d653f6 100644
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -59,14 +59,12 @@ void __init prom_init(void)
/* do low level board init */
board_prom_init();
- if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) {
- /* set up SMP */
- register_smp_ops(&bmips_smp_ops);
-
+ /* set up SMP */
+ if (!register_bmips_smp_ops()) {
/*
- * BCM6328 might not have its second CPU enabled, while BCM6358
- * needs special handling for its shared TLB, so disable SMP
- * for now.
+ * BCM6328 might not have its second CPU enabled, while BCM3368
+ * and BCM6358 need special handling for their shared TLB, so
+ * disable SMP for now.
*/
if (BCMCPU_IS_6328()) {
reg = bcm_readl(BCM_6328_OTP_BASE +
@@ -74,7 +72,7 @@ void __init prom_init(void)
if (reg & OTP_6328_REG3_TP1_DISABLED)
bmips_smp_enabled = 0;
- } else if (BCMCPU_IS_6358()) {
+ } else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
bmips_smp_enabled = 0;
}
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 0048c089789..61af6b6ab13 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -27,16 +27,20 @@ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \
-DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS)
-targets := head.o decompress.o dbg.o uart-16550.o uart-alchemy.o
+targets := head.o decompress.o string.o dbg.o uart-16550.o uart-alchemy.o
# decompressor objects (linked with vmlinuz)
-vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o
+vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/dbg.o
ifdef CONFIG_DEBUG_ZBOOT
vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o
endif
+ifdef CONFIG_KERNEL_XZ
+vmlinuzobjs-y += $(obj)/../../lib/ashldi3.o
+endif
+
targets += vmlinux.bin
OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
$(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
@@ -44,8 +48,10 @@ $(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
tool_$(CONFIG_KERNEL_GZIP) = gzip
tool_$(CONFIG_KERNEL_BZIP2) = bzip2
+tool_$(CONFIG_KERNEL_LZ4) = lz4
tool_$(CONFIG_KERNEL_LZMA) = lzma
tool_$(CONFIG_KERNEL_LZO) = lzo
+tool_$(CONFIG_KERNEL_XZ) = xzkern
targets += vmlinux.bin.z
$(obj)/vmlinux.bin.z: $(obj)/vmlinux.bin FORCE
diff --git a/arch/mips/boot/compressed/dbg.c b/arch/mips/boot/compressed/dbg.c
index 134a6162e39..06c6a5bd175 100644
--- a/arch/mips/boot/compressed/dbg.c
+++ b/arch/mips/boot/compressed/dbg.c
@@ -6,7 +6,6 @@
* need to implement your own putc().
*/
#include <linux/compiler.h>
-#include <linux/init.h>
#include <linux/types.h>
void __weak putc(char c)
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index 2c9573098c0..c00c4ddf451 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -44,32 +44,17 @@ void error(char *x)
#define STATIC static
#ifdef CONFIG_KERNEL_GZIP
-void *memcpy(void *dest, const void *src, size_t n)
-{
- int i;
- const char *s = src;
- char *d = dest;
-
- for (i = 0; i < n; i++)
- d[i] = s[i];
- return dest;
-}
#include "../../../../lib/decompress_inflate.c"
#endif
#ifdef CONFIG_KERNEL_BZIP2
-void *memset(void *s, int c, size_t n)
-{
- int i;
- char *ss = s;
-
- for (i = 0; i < n; i++)
- ss[i] = c;
- return s;
-}
#include "../../../../lib/decompress_bunzip2.c"
#endif
+#ifdef CONFIG_KERNEL_LZ4
+#include "../../../../lib/decompress_unlz4.c"
+#endif
+
#ifdef CONFIG_KERNEL_LZMA
#include "../../../../lib/decompress_unlzma.c"
#endif
@@ -78,6 +63,10 @@ void *memset(void *s, int c, size_t n)
#include "../../../../lib/decompress_unlzo.c"
#endif
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
void decompress_kernel(unsigned long boot_heap_start)
{
unsigned long zimage_start, zimage_size;
diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script
index 8e6b07ca2f5..5a33409c7f6 100644
--- a/arch/mips/boot/compressed/ld.script
+++ b/arch/mips/boot/compressed/ld.script
@@ -8,6 +8,9 @@
OUTPUT_ARCH(mips)
ENTRY(start)
+PHDRS {
+ text PT_LOAD FLAGS(7); /* RWX */
+}
SECTIONS
{
/* Text and read-only data */
@@ -15,7 +18,7 @@ SECTIONS
.text : {
*(.text)
*(.rodata)
- }
+ }: text
/* End of text section */
/* Writable data */
diff --git a/arch/mips/boot/compressed/string.c b/arch/mips/boot/compressed/string.c
new file mode 100644
index 00000000000..9de9885acd0
--- /dev/null
+++ b/arch/mips/boot/compressed/string.c
@@ -0,0 +1,28 @@
+/*
+ * arch/mips/boot/compressed/string.c
+ *
+ * Very small subset of simple string routines
+ */
+
+#include <linux/types.h>
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ int i;
+ const char *s = src;
+ char *d = dest;
+
+ for (i = 0; i < n; i++)
+ d[i] = s[i];
+ return dest;
+}
+
+void *memset(void *s, int c, size_t n)
+{
+ int i;
+ char *ss = s;
+
+ for (i = 0; i < n; i++)
+ ss[i] = c;
+ return s;
+}
diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c
index c01d343ce6a..237494b7a21 100644
--- a/arch/mips/boot/compressed/uart-16550.c
+++ b/arch/mips/boot/compressed/uart-16550.c
@@ -4,7 +4,6 @@
#include <linux/types.h>
#include <linux/serial_reg.h>
-#include <linux/init.h>
#include <asm/addrspace.h>
@@ -19,8 +18,8 @@
#endif
#ifdef CONFIG_MACH_JZ4740
-#define UART0_BASE 0xB0030000
-#define PORT(offset) (UART0_BASE + (4 * offset))
+#include <asm/mach-jz4740/base.h>
+#define PORT(offset) (CKSEG1ADDR(JZ4740_UART0_BASE_ADDR) + (4 * offset))
#endif
#ifdef CONFIG_CPU_XLR
diff --git a/arch/mips/boot/dts/include/dt-bindings b/arch/mips/boot/dts/include/dt-bindings
index 68ae3887b3e..08c00e4972f 120000
--- a/arch/mips/boot/dts/include/dt-bindings
+++ b/arch/mips/boot/dts/include/dt-bindings
@@ -1 +1 @@
-../../../../../include/dt-bindings
+../../../../../include/dt-bindings \ No newline at end of file
diff --git a/arch/mips/boot/ecoff.h b/arch/mips/boot/ecoff.h
index 83e5c3813d6..7a75ce2c1bc 100644
--- a/arch/mips/boot/ecoff.h
+++ b/arch/mips/boot/ecoff.h
@@ -12,7 +12,6 @@ typedef struct filehdr {
} FILHDR;
#define FILHSZ sizeof(FILHDR)
-#define OMAGIC 0407
#define MIPSEBMAGIC 0x160
#define MIPSELMAGIC 0x162
diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 227705d9d5a..60286665793 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -10,6 +10,17 @@ config CAVIUM_CN63XXP1
non-CN63XXP1 hardware, so it is recommended to select "n"
unless it is known the workarounds are needed.
+config CAVIUM_OCTEON_CVMSEG_SIZE
+ int "Number of L1 cache lines reserved for CVMSEG memory"
+ range 0 54
+ default 1
+ help
+ CVMSEG LM is a segment that accesses portions of the dcache as a
+ local memory; the larger CVMSEG is, the smaller the cache is.
+ This selects the size of CVMSEG LM, which is in cache blocks. The
+ legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
+ between zero and 6192 bytes).
+
endif # CPU_CAVIUM_OCTEON
if CAVIUM_OCTEON_SOC
@@ -23,17 +34,6 @@ config CAVIUM_OCTEON_2ND_KERNEL
with this option to be run at the same time as one built without this
option.
-config CAVIUM_OCTEON_CVMSEG_SIZE
- int "Number of L1 cache lines reserved for CVMSEG memory"
- range 0 54
- default 1
- help
- CVMSEG LM is a segment that accesses portions of the dcache as a
- local memory; the larger CVMSEG is, the smaller the cache is.
- This selects the size of CVMSEG LM, which is in cache blocks. The
- legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
- between zero and 6192 bytes).
-
config CAVIUM_OCTEON_LOCK_L2
bool "Lock often used kernel code in the L2"
default "y"
@@ -86,7 +86,6 @@ config SWIOTLB
select IOMMU_HELPER
select NEED_SG_DMA_LENGTH
-
config OCTEON_ILM
tristate "Module to measure interrupt latency using Octeon CIU Timer"
help
diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c
index 02193953eb9..b752c4ed0b7 100644
--- a/arch/mips/cavium-octeon/csrc-octeon.c
+++ b/arch/mips/cavium-octeon/csrc-octeon.c
@@ -12,6 +12,7 @@
#include <linux/smp.h>
#include <asm/cpu-info.h>
+#include <asm/cpu-type.h>
#include <asm/time.h>
#include <asm/octeon/octeon.h>
diff --git a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c
index 132bccc66a9..8241fc6aa17 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c
@@ -47,6 +47,7 @@
* state. It points to a bootmem named block.
*/
__cvmx_cmd_queue_all_state_t *__cvmx_cmd_queue_state_ptr;
+EXPORT_SYMBOL_GPL(__cvmx_cmd_queue_state_ptr);
/**
* Initialize the Global queue state pointer.
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index 0a1283ce47f..b764df64be4 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -722,3 +722,30 @@ int __cvmx_helper_board_hardware_enable(int interface)
}
return 0;
}
+
+/**
+ * Get the clock type used for the USB block based on board type.
+ * Used by the USB code for auto configuration of clock type.
+ *
+ * Return USB clock type enumeration
+ */
+enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(void)
+{
+ switch (cvmx_sysinfo_get()->board_type) {
+ case CVMX_BOARD_TYPE_BBGW_REF:
+ case CVMX_BOARD_TYPE_LANAI2_A:
+ case CVMX_BOARD_TYPE_LANAI2_U:
+ case CVMX_BOARD_TYPE_LANAI2_G:
+ case CVMX_BOARD_TYPE_NIC10E_66:
+ case CVMX_BOARD_TYPE_UBNT_E100:
+ return USB_CLOCK_TYPE_CRYSTAL_12;
+ case CVMX_BOARD_TYPE_NIC10E:
+ return USB_CLOCK_TYPE_REF_12;
+ default:
+ break;
+ }
+ /* Most boards except NIC10e use a 12MHz crystal */
+ if (OCTEON_IS_MODEL(OCTEON_FAM_2))
+ return USB_CLOCK_TYPE_CRYSTAL_12;
+ return USB_CLOCK_TYPE_REF_48;
+}
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
index 65d2bc9a0bd..453d7f66459 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
@@ -251,6 +251,7 @@ int cvmx_helper_setup_red(int pass_thresh, int drop_thresh)
return 0;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_setup_red);
/**
* Setup the common GMX settings that determine the number of
@@ -384,6 +385,7 @@ int cvmx_helper_get_ipd_port(int interface, int port)
}
return -1;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_get_ipd_port);
/**
* Returns the interface number for an IPD/PKO port number.
@@ -408,6 +410,7 @@ int cvmx_helper_get_interface_num(int ipd_port)
return -1;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_get_interface_num);
/**
* Returns the interface index number for an IPD/PKO port
@@ -431,3 +434,4 @@ int cvmx_helper_get_interface_index_num(int ipd_port)
return -1;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_get_interface_index_num);
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c
index d63d20dfbfb..7e5cf7a5e2f 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c
@@ -67,7 +67,7 @@ void (*cvmx_override_pko_queue_priority) (int pko_port,
void (*cvmx_override_ipd_port_setup) (int ipd_port);
/* Port count per interface */
-static int interface_port_count[4] = { 0, 0, 0, 0 };
+static int interface_port_count[5];
/* Port last configured link info index by IPD/PKO port */
static cvmx_helper_link_info_t
@@ -88,6 +88,7 @@ int cvmx_helper_get_number_of_interfaces(void)
else
return 3;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
/**
* Return the number of ports on an interface. Depending on the
@@ -102,6 +103,159 @@ int cvmx_helper_ports_on_interface(int interface)
{
return interface_port_count[interface];
}
+EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
+
+/**
+ * @INTERNAL
+ * Return interface mode for CN68xx.
+ */
+static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
+{
+ union cvmx_mio_qlmx_cfg qlm_cfg;
+ switch (interface) {
+ case 0:
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
+ /* QLM is disabled when QLM SPD is 15. */
+ if (qlm_cfg.s.qlm_spd == 15)
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+ if (qlm_cfg.s.qlm_cfg == 2)
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
+ else if (qlm_cfg.s.qlm_cfg == 3)
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
+ else
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ case 2:
+ case 3:
+ case 4:
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
+ /* QLM is disabled when QLM SPD is 15. */
+ if (qlm_cfg.s.qlm_spd == 15)
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+ if (qlm_cfg.s.qlm_cfg == 2)
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
+ else if (qlm_cfg.s.qlm_cfg == 3)
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
+ else
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ case 7:
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
+ /* QLM is disabled when QLM SPD is 15. */
+ if (qlm_cfg.s.qlm_spd == 15) {
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ } else if (qlm_cfg.s.qlm_cfg != 0) {
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
+ if (qlm_cfg.s.qlm_cfg != 0)
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ }
+ return CVMX_HELPER_INTERFACE_MODE_NPI;
+ case 8:
+ return CVMX_HELPER_INTERFACE_MODE_LOOP;
+ default:
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ }
+}
+
+/**
+ * @INTERNAL
+ * Return interface mode for an Octeon II
+ */
+static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
+{
+ union cvmx_gmxx_inf_mode mode;
+
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ return __cvmx_get_mode_cn68xx(interface);
+
+ if (interface == 2)
+ return CVMX_HELPER_INTERFACE_MODE_NPI;
+
+ if (interface == 3)
+ return CVMX_HELPER_INTERFACE_MODE_LOOP;
+
+ /* Only present in CN63XX & CN66XX Octeon model */
+ if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
+ (interface == 4 || interface == 5)) ||
+ (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
+ interface >= 4 && interface <= 7)) {
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ }
+
+ if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
+ union cvmx_mio_qlmx_cfg mio_qlm_cfg;
+
+ /* QLM2 is SGMII0 and QLM1 is SGMII1 */
+ if (interface == 0)
+ mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
+ else if (interface == 1)
+ mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
+ else
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+ if (mio_qlm_cfg.s.qlm_spd == 15)
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+ if (mio_qlm_cfg.s.qlm_cfg == 9)
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
+ else if (mio_qlm_cfg.s.qlm_cfg == 11)
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
+ else
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
+ union cvmx_mio_qlmx_cfg qlm_cfg;
+
+ if (interface == 0) {
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
+ if (qlm_cfg.s.qlm_cfg == 2)
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
+ else if (qlm_cfg.s.qlm_cfg == 3)
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
+ else
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ } else if (interface == 1) {
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
+ if (qlm_cfg.s.qlm_cfg == 2)
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
+ else if (qlm_cfg.s.qlm_cfg == 3)
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
+ else
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ }
+ } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
+ if (interface == 0) {
+ union cvmx_mio_qlmx_cfg qlm_cfg;
+ qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
+ if (qlm_cfg.s.qlm_cfg == 2)
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
+ }
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ }
+
+ if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+ mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
+
+ if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
+ switch (mode.cn63xx.mode) {
+ case 0:
+ return CVMX_HELPER_INTERFACE_MODE_SGMII;
+ case 1:
+ return CVMX_HELPER_INTERFACE_MODE_XAUI;
+ default:
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ }
+ } else {
+ if (!mode.s.en)
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+ if (mode.s.type)
+ return CVMX_HELPER_INTERFACE_MODE_GMII;
+ else
+ return CVMX_HELPER_INTERFACE_MODE_RGMII;
+ }
+}
/**
* Get the operating mode of an interface. Depending on the Octeon
@@ -116,6 +270,20 @@ int cvmx_helper_ports_on_interface(int interface)
cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
{
union cvmx_gmxx_inf_mode mode;
+
+ if (interface < 0 ||
+ interface >= cvmx_helper_get_number_of_interfaces())
+ return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+ /*
+ * Octeon II models
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
+ return __cvmx_get_mode_octeon2(interface);
+
+ /*
+ * Octeon and Octeon Plus models
+ */
if (interface == 2)
return CVMX_HELPER_INTERFACE_MODE_NPI;
@@ -179,6 +347,7 @@ cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
return CVMX_HELPER_INTERFACE_MODE_RGMII;
}
}
+EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
/**
* Configure the IPD/PIP tagging and QoS options for a specific
@@ -825,6 +994,7 @@ int cvmx_helper_ipd_and_packet_input_enable(void)
__cvmx_helper_errata_fix_ipd_ptr_alignment();
return 0;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
/**
* Initialize the PIP, IPD, and PKO hardware to support
@@ -903,6 +1073,7 @@ int cvmx_helper_initialize_packet_io_global(void)
#endif
return result;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
/**
* Does core local initialization for packet io
@@ -947,6 +1118,7 @@ cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
*/
return port_link_info[ipd_port];
}
+EXPORT_SYMBOL_GPL(cvmx_helper_link_autoconf);
/**
* Return the link state of an IPD/PKO port as returned by
@@ -1005,6 +1177,7 @@ cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
}
return result;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
/**
* Configure an IPD/PKO port for the specified link state. This
@@ -1060,6 +1233,7 @@ int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
port_link_info[ipd_port].u64 = link_info.u64;
return result;
}
+EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
/**
* Configure a port for internal and/or external loopback. Internal loopback
diff --git a/arch/mips/cavium-octeon/executive/cvmx-pko.c b/arch/mips/cavium-octeon/executive/cvmx-pko.c
index f2c87754159..008b881cdf6 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-pko.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-pko.c
@@ -140,7 +140,7 @@ void cvmx_pko_disable(void)
pko_reg_flags.s.ena_pko = 0;
cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
}
-
+EXPORT_SYMBOL_GPL(cvmx_pko_disable);
/**
* Reset the packet output.
@@ -182,6 +182,7 @@ void cvmx_pko_shutdown(void)
}
__cvmx_pko_reset();
}
+EXPORT_SYMBOL_GPL(cvmx_pko_shutdown);
/**
* Configure a output port and the associated queues for use.
diff --git a/arch/mips/cavium-octeon/executive/cvmx-spi.c b/arch/mips/cavium-octeon/executive/cvmx-spi.c
index ef5198d13a0..459e3b1eb61 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-spi.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-spi.c
@@ -177,6 +177,7 @@ int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, int timeout)
return res;
}
+EXPORT_SYMBOL_GPL(cvmx_spi_restart_interface);
/**
* Callback to perform SPI4 reset
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 25fbfae06c1..1b82ac6921e 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -635,7 +635,7 @@ static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
cpumask_clear(&new_affinity);
cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
}
- __irq_set_affinity_locked(data, &new_affinity);
+ irq_set_affinity_locked(data, &new_affinity, false);
}
static int octeon_irq_ciu_set_affinity(struct irq_data *data,
@@ -975,10 +975,6 @@ static int octeon_irq_ciu_xlat(struct irq_domain *d,
if (ciu > 1 || bit > 63)
return -EINVAL;
- /* These are the GPIO lines */
- if (ciu == 0 && bit >= 16 && bit < 32)
- return -EINVAL;
-
*out_hwirq = (ciu << 6) | bit;
*out_type = 0;
@@ -1007,6 +1003,10 @@ static int octeon_irq_ciu_map(struct irq_domain *d,
if (!octeon_irq_virq_in_range(virq))
return -EINVAL;
+ /* Don't map irq if it is reserved for GPIO. */
+ if (line == 0 && bit >= 16 && bit <32)
+ return 0;
+
if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
@@ -1260,11 +1260,13 @@ static void __init octeon_irq_init_ciu(void)
for (i = 0; i < 4; i++)
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40);
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_TWSI, 0, 45);
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46);
for (i = 0; i < 4; i++)
octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52);
octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
+ octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_TWSI2, 0, 59);
/* CIU_1 */
for (i = 0; i < 16; i++)
@@ -1525,10 +1527,6 @@ static int octeon_irq_ciu2_xlat(struct irq_domain *d,
ciu = intspec[0];
bit = intspec[1];
- /* Line 7 are the GPIO lines */
- if (ciu > 6 || bit > 63)
- return -EINVAL;
-
*out_hwirq = (ciu << 6) | bit;
*out_type = 0;
@@ -1570,8 +1568,14 @@ static int octeon_irq_ciu2_map(struct irq_domain *d,
if (!octeon_irq_virq_in_range(virq))
return -EINVAL;
- /* Line 7 are the GPIO lines */
- if (line > 6 || octeon_irq_ciu_to_irq[line][bit] != 0)
+ /*
+ * Don't map irq if it is reserved for GPIO.
+ * (Line 7 are the GPIO lines.)
+ */
+ if (line == 7)
+ return 0;
+
+ if (line > 7 || octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
if (octeon_irq_ciu2_is_edge(line, bit))
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 1830874ff1e..6df0f4d8f19 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -171,6 +171,7 @@ device_initcall(octeon_ohci_device_init);
static struct of_device_id __initdata octeon_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "cavium,octeon-6335-uctl", },
+ { .compatible = "cavium,octeon-5750-usbn", },
{ .compatible = "cavium,octeon-3860-bootbus", },
{ .compatible = "cavium,mdio-mux", },
{ .compatible = "gpio-leds", },
@@ -336,14 +337,14 @@ static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
int p;
int count = 0;
- if (cvmx_helper_interface_enumerate(idx) == 0)
- count = cvmx_helper_ports_on_interface(idx);
-
snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
if (iface < 0)
return;
+ if (cvmx_helper_interface_enumerate(idx) == 0)
+ count = cvmx_helper_ports_on_interface(idx);
+
for (p = 0; p < 16; p++)
octeon_fdt_pip_port(iface, idx, p, count - 1, pmac);
}
@@ -682,6 +683,37 @@ end_led:
}
}
+ /* DWC2 USB */
+ alias_prop = fdt_getprop(initial_boot_params, aliases,
+ "usbn", NULL);
+ if (alias_prop) {
+ int usbn = fdt_path_offset(initial_boot_params, alias_prop);
+
+ if (usbn >= 0 && (current_cpu_type() == CPU_CAVIUM_OCTEON2 ||
+ !octeon_has_feature(OCTEON_FEATURE_USB))) {
+ pr_debug("Deleting usbn\n");
+ fdt_nop_node(initial_boot_params, usbn);
+ fdt_nop_property(initial_boot_params, aliases, "usbn");
+ } else {
+ __be32 new_f[1];
+ enum cvmx_helper_board_usb_clock_types c;
+ c = __cvmx_helper_board_usb_get_clock_type();
+ switch (c) {
+ case USB_CLOCK_TYPE_REF_48:
+ new_f[0] = cpu_to_be32(48000000);
+ fdt_setprop_inplace(initial_boot_params, usbn,
+ "refclk-frequency", new_f, sizeof(new_f));
+ /* Fall through ...*/
+ case USB_CLOCK_TYPE_REF_12:
+ /* Missing "refclk-type" defaults to external. */
+ fdt_nop_property(initial_boot_params, usbn, "refclk-type");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
return 0;
}
diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts
index 88cb42d4cc4..fa33115bde3 100644
--- a/arch/mips/cavium-octeon/octeon_3xxx.dts
+++ b/arch/mips/cavium-octeon/octeon_3xxx.dts
@@ -550,6 +550,24 @@
big-endian-regs;
};
};
+
+ usbn: usbn@1180068000000 {
+ compatible = "cavium,octeon-5750-usbn";
+ reg = <0x11800 0x68000000 0x0 0x1000>;
+ ranges; /* Direct mapping */
+ #address-cells = <2>;
+ #size-cells = <2>;
+ /* 12MHz, 24MHz and 48MHz allowed */
+ refclk-frequency = <12000000>;
+ /* Either "crystal" or "external" */
+ refclk-type = "crystal";
+
+ usbc@16f0010000000 {
+ compatible = "cavium,octeon-5750-usbc";
+ reg = <0x16f00 0x10000000 0x0 0x80000>;
+ interrupts = <0 56>;
+ };
+ };
};
aliases {
@@ -566,6 +584,7 @@
flash0 = &flash0;
cf0 = &cf0;
uctl = &uctl;
+ usbn = &usbn;
led0 = &led0;
};
};
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index b212ae12e5a..008e9c8b8ea 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -729,17 +729,6 @@ void __init prom_init(void)
octeon_write_lcd("Linux");
#endif
-#ifdef CONFIG_CAVIUM_GDB
- /*
- * When debugging the linux kernel, force the cores to enter
- * the debug exception handler to break in.
- */
- if (octeon_get_boot_debug_flag()) {
- cvmx_write_csr(CVMX_CIU_DINT, 1 << cvmx_get_core_num());
- cvmx_read_csr(CVMX_CIU_DINT);
- }
-#endif
-
octeon_setup_delays();
/*
@@ -779,12 +768,6 @@ void __init prom_init(void)
MAX_MEMORY = 32ull << 30;
if (*p == '@')
RESERVE_LOW_MEM = memparse(p + 1, &p);
- } else if (strcmp(arg, "ecc_verbose") == 0) {
-#ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC
- __cvmx_interrupt_ecc_report_single_bit_errors = 1;
- pr_notice("Reporting of single bit ECC errors is "
- "turned on\n");
-#endif
#ifdef CONFIG_KEXEC
} else if (strncmp(arg, "crashkernel=", 12) == 0) {
crashk_size = memparse(arg+12, &p);
@@ -999,7 +982,7 @@ void __init plat_mem_setup(void)
if (total == 0)
panic("Unable to allocate memory from "
- "cvmx_bootmem_phy_alloc\n");
+ "cvmx_bootmem_phy_alloc");
}
/*
@@ -1053,36 +1036,26 @@ void prom_free_prom_memory(void)
int octeon_prune_device_tree(void);
extern const char __dtb_octeon_3xxx_begin;
-extern const char __dtb_octeon_3xxx_end;
extern const char __dtb_octeon_68xx_begin;
-extern const char __dtb_octeon_68xx_end;
void __init device_tree_init(void)
{
- int dt_size;
- struct boot_param_header *fdt;
+ const void *fdt;
bool do_prune;
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.");
- dt_size = be32_to_cpu(fdt->totalsize);
do_prune = false;
} else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
- fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin;
- dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin;
+ fdt = &__dtb_octeon_68xx_begin;
do_prune = true;
} else {
- fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin;
- dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
+ fdt = &__dtb_octeon_3xxx_begin;
do_prune = true;
}
- /* Copy the default tree from init memory. */
- initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
- if (initial_boot_params == NULL)
- panic("Could not allocate initial_boot_params\n");
- memcpy(initial_boot_params, fdt, dt_size);
+ initial_boot_params = (void *)fdt;
if (do_prune) {
octeon_prune_device_tree();
@@ -1090,7 +1063,7 @@ void __init device_tree_init(void)
} else {
pr_info("Using passed Device Tree.\n");
}
- unflatten_device_tree();
+ unflatten_and_copy_device_tree();
}
static int __initdata disable_octeon_edac_p;
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 24a2167db77..a7b3ae104d8 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -6,7 +6,6 @@
* Copyright (C) 2004-2008, 2009, 2010 Cavium Networks
*/
#include <linux/cpu.h>
-#include <linux/init.h>
#include <linux/delay.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
@@ -219,15 +218,6 @@ void octeon_prepare_cpus(unsigned int max_cpus)
*/
static void octeon_smp_finish(void)
{
-#ifdef CONFIG_CAVIUM_GDB
- unsigned long tmp;
- /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
- to be not masked by this core so we know the signal is received by
- someone */
- asm volatile ("dmfc0 %0, $22\n"
- "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
-#endif
-
octeon_user_io_init();
/* to generate the first CPU timer interrupt */
@@ -235,21 +225,6 @@ static void octeon_smp_finish(void)
local_irq_enable();
}
-/**
- * Hook for after all CPUs are online
- */
-static void octeon_cpus_done(void)
-{
-#ifdef CONFIG_CAVIUM_GDB
- unsigned long tmp;
- /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
- to be not masked by this core so we know the signal is received by
- someone */
- asm volatile ("dmfc0 %0, $22\n"
- "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
-#endif
-}
-
#ifdef CONFIG_HOTPLUG_CPU
/* State of each CPU. */
@@ -406,7 +381,6 @@ struct plat_smp_ops octeon_smp_ops = {
.send_ipi_mask = octeon_send_ipi_mask,
.init_secondary = octeon_init_secondary,
.smp_finish = octeon_smp_finish,
- .cpus_done = octeon_cpus_done,
.boot_secondary = octeon_boot_secondary,
.smp_setup = octeon_smp_setup,
.prepare_cpus = octeon_prepare_cpus,
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 61a334ac43a..558e9497794 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -5,5 +5,4 @@
obj-y := buttons.o irq.o lcd.o led.o reset.o rtc.o serial.o setup.o time.o
obj-$(CONFIG_PCI) += pci.o
-obj-$(CONFIG_EARLY_PRINTK) += console.o
obj-$(CONFIG_MTD_PHYSMAP) += mtd.o
diff --git a/arch/mips/cobalt/console.c b/arch/mips/cobalt/console.c
deleted file mode 100644
index d1ba701c9dd..00000000000
--- a/arch/mips/cobalt/console.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * (C) P. Horton 2006
- */
-#include <linux/io.h>
-#include <linux/serial_reg.h>
-
-#include <cobalt.h>
-
-#define UART_BASE ((void __iomem *)CKSEG1ADDR(0x1c800000))
-
-void prom_putchar(char c)
-{
- if (cobalt_board_id <= COBALT_BRD_ID_QUBE1)
- return;
-
- while (!(readb(UART_BASE + UART_LSR) & UART_LSR_THRE))
- ;
-
- writeb(c, UART_BASE + UART_TX);
-}
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index ec3b2c417f7..9a8c2fe8d33 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -17,6 +17,7 @@
#include <asm/bootinfo.h>
#include <asm/reboot.h>
+#include <asm/setup.h>
#include <asm/gt64120.h>
#include <cobalt.h>
@@ -112,6 +113,8 @@ void __init prom_init(void)
}
add_memory_region(0x0, memsz, BOOT_MEM_RAM);
+
+ setup_8250_early_printk_port(CKSEG1ADDR(0x1c800000), 0, 0);
}
void __init prom_free_prom_memory(void)
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
index 80e012fa409..320772caf05 100644
--- a/arch/mips/configs/ar7_defconfig
+++ b/arch/mips/configs/ar7_defconfig
@@ -86,7 +86,6 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig
index e3a3836508e..134879c1310 100644
--- a/arch/mips/configs/ath79_defconfig
+++ b/arch/mips/configs/ath79_defconfig
@@ -46,7 +46,6 @@ CONFIG_MTD=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
@@ -54,7 +53,7 @@ CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_M25P80=y
-# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_MTD_SPI_NOR=y
CONFIG_NETDEVICES=y
# CONFIG_NET_PACKET_ENGINE is not set
CONFIG_ATH_COMMON=m
diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig
index 4ca8e5c9922..0db4eb319e0 100644
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -1,623 +1,86 @@
CONFIG_BCM47XX=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_KEXEC=y
-# CONFIG_SECCOMP is not set
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_TASKSTATS=y
-CONFIG_TASK_DELAY_ACCT=y
-CONFIG_TASK_XACCT=y
-CONFIG_TASK_IO_ACCOUNTING=y
-CONFIG_AUDIT=y
-CONFIG_TINY_RCU=y
-CONFIG_CGROUPS=y
-CONFIG_CGROUP_CPUACCT=y
-CONFIG_RELAY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
CONFIG_BLK_DEV_INITRD=y
-CONFIG_RD_LZMA=y
-CONFIG_EXPERT=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
CONFIG_SLAB=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
CONFIG_PCI=y
-CONFIG_BINFMT_MISC=m
+# CONFIG_SUSPEND is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=m
CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_TCP_CONG_BIC=y
-CONFIG_TCP_CONG_CUBIC=m
-CONFIG_TCP_CONG_HSTCP=m
-CONFIG_TCP_CONG_HYBLA=m
-CONFIG_TCP_CONG_SCALABLE=m
-CONFIG_TCP_CONG_LP=m
-CONFIG_TCP_CONG_VENO=m
-CONFIG_TCP_CONG_YEAH=m
-CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
+CONFIG_IPV6_MROUTE=y
CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_UDPLITE=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-CONFIG_NF_CONNTRACK_NETBIOS_NS=m
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_DSCP=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_TRACE=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_TIME=m
-CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_IP_VS=m
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-CONFIG_IP_VS_FTP=m
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_AH=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_AH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_REJECT=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_RAW=m
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_BRIDGE_EBT_ULOG=m
-CONFIG_IP_DCCP=m
-CONFIG_TIPC=m
-CONFIG_TIPC_ADVANCED=y
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q=y
CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_CLS_BASIC=m
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_CLS_U32_PERF=y
-CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_EMATCH=y
-CONFIG_NET_EMATCH_CMP=m
-CONFIG_NET_EMATCH_NBYTE=m
-CONFIG_NET_EMATCH_U32=m
-CONFIG_NET_EMATCH_META=m
-CONFIG_NET_EMATCH_TEXT=m
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=m
-CONFIG_NET_ACT_GACT=m
-CONFIG_GACT_PROB=y
-CONFIG_NET_ACT_MIRRED=m
-CONFIG_NET_ACT_IPT=m
-CONFIG_NET_ACT_NAT=m
-CONFIG_NET_ACT_PEDIT=m
-CONFIG_NET_ACT_SIMP=m
-CONFIG_NET_CLS_IND=y
-CONFIG_NET_PKTGEN=m
-CONFIG_BT=m
-CONFIG_BT_HCIUART=m
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_BCSP=y
-CONFIG_BT_HCIUART_LL=y
-CONFIG_BT_HCIBCM203X=m
-CONFIG_BT_HCIBPA10X=m
-CONFIG_BT_HCIBFUSB=m
-CONFIG_BT_HCIVHCI=m
-CONFIG_CFG80211=m
-CONFIG_MAC80211=m
-CONFIG_MAC80211_RC_PID=y
-CONFIG_MAC80211_RC_DEFAULT_PID=y
-CONFIG_MAC80211_MESH=y
-CONFIG_RFKILL=m
-CONFIG_RFKILL_INPUT=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_FW_LOADER=m
-CONFIG_CONNECTOR=m
+CONFIG_NET_SCH_FQ_CODEL=y
+CONFIG_HAMRADIO=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
+CONFIG_MTD_BCM47XX_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_ROM=y
-CONFIG_MTD_ABSENT=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_ATA_OVER_ETH=m
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=m
-CONFIG_CHR_DEV_SCH=m
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_ISCSI_TCP=m
+CONFIG_MTD_BCM47XXSFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_BCM47XXNFLASH=y
CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
-CONFIG_VETH=m
-CONFIG_PHYLIB=m
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-CONFIG_BROADCOM_PHY=m
-CONFIG_ICPLUS_PHY=m
-CONFIG_MDIO_BITBANG=m
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_PCI=y
CONFIG_B44=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_ATH_COMMON=m
-CONFIG_ATH5K=m
-CONFIG_B43=m
-CONFIG_B43LEGACY=m
-CONFIG_ZD1211RW=m
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_DM9601=m
-CONFIG_USB_NET_GL620A=m
-CONFIG_USB_NET_PLUSB=m
-CONFIG_USB_NET_MCS7830=m
-CONFIG_USB_NET_RNDIS_HOST=m
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_USB_SIERRA_NET=m
-CONFIG_ATM_DUMMY=m
-CONFIG_ATM_TCP=m
-CONFIG_PPP=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
-CONFIG_SLIP=m
-CONFIG_INPUT_EVDEV=m
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
+CONFIG_TIGON3=y
+CONFIG_BGMAC=y
+CONFIG_ATH_CARDS=y
+CONFIG_ATH5K=y
+CONFIG_B43=y
+CONFIG_B43LEGACY=y
+CONFIG_BRCMSMAC=y
+CONFIG_ISDN=y
CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_PCI is not set
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_W1=m
-CONFIG_W1_MASTER_MATROX=m
-CONFIG_W1_MASTER_DS2490=m
-CONFIG_W1_SLAVE_THERM=m
-CONFIG_W1_SLAVE_SMEM=m
-CONFIG_W1_SLAVE_DS2433=m
-CONFIG_W1_SLAVE_DS2760=m
-# CONFIG_HWMON is not set
-CONFIG_THERMAL=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_HW_RANDOM=y
+CONFIG_GPIO_SYSFS=y
CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_BCM47XX_WDT=y
+CONFIG_SSB_DEBUG=y
CONFIG_SSB_DRIVER_GIGE=y
-CONFIG_DISPLAY_SUPPORT=m
-CONFIG_SOUND=m
-CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_DUMMY=m
-CONFIG_SND_VIRMIDI=m
-CONFIG_SND_USB_AUDIO=m
-CONFIG_HID=m
-CONFIG_USB_HID=m
-CONFIG_USB_HIDDEV=y
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_U132_HCD=m
-CONFIG_USB_R8A66597_HCD=m
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-CONFIG_USB_STORAGE_ONETOUCH=y
-CONFIG_USB_STORAGE_KARMA=y
-CONFIG_USB_MDC800=m
-CONFIG_USB_MICROTEK=m
-CONFIG_USB_SERIAL=m
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_AIRCABLE=m
-CONFIG_USB_SERIAL_ARK3116=m
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_CH341=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_CYPRESS_M8=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_FUNSOFT=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_GARMIN=m
-CONFIG_USB_SERIAL_IPW=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_MOS7720=m
-CONFIG_USB_SERIAL_MOS7840=m
-CONFIG_USB_SERIAL_NAVMAN=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_OTI6858=m
-CONFIG_USB_SERIAL_HP4X=m
-CONFIG_USB_SERIAL_SAFE=m
-CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OPTION=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_SERIAL_DEBUG=m
-CONFIG_USB_ADUTUX=m
-CONFIG_USB_RIO500=m
-CONFIG_USB_LEGOTOWER=m
-CONFIG_USB_LCD=m
-CONFIG_USB_LED=m
-CONFIG_USB_CYPRESS_CY7C63=m
-CONFIG_USB_CYTHERM=m
-CONFIG_USB_IDMOUSE=m
-CONFIG_USB_FTDI_ELAN=m
-CONFIG_USB_SISUSBVGA=m
-CONFIG_USB_LD=m
-CONFIG_USB_TRANCEVIBRATOR=m
-CONFIG_USB_IOWARRIOR=m
-CONFIG_USB_TEST=m
-CONFIG_USB_ATM=m
-CONFIG_USB_SPEEDTOUCH=m
-CONFIG_USB_CXACRU=m
-CONFIG_USB_UEAGLEATM=m
-CONFIG_USB_XUSBATM=m
-CONFIG_USB_GADGET=m
-CONFIG_USB_GADGET_NET2280=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_ETH=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_MASS_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_USB_MIDI_GADGET=m
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
+CONFIG_USB_HCD_BCMA=y
+CONFIG_USB_HCD_SSB=y
CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
-CONFIG_JFS_FS=m
-CONFIG_JFS_POSIX_ACL=y
-CONFIG_JFS_SECURITY=y
-CONFIG_XFS_FS=m
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_POSIX_ACL=y
-CONFIG_XFS_RT=y
-CONFIG_GFS2_FS=m
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-CONFIG_QFMT_V1=m
-CONFIG_QFMT_V2=m
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NTFS_FS=m
-CONFIG_NTFS_RW=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_ADFS_FS=m
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_JFFS2_FS=m
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_CRAMFS=m
-CONFIG_VXFS_FS=m
-CONFIG_MINIX_FS=m
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-CONFIG_ROMFS_FS=m
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V3_ACL=y
-CONFIG_NFSD_V4=y
-CONFIG_RPCSEC_GSS_SPKM3=m
-CONFIG_CIFS=m
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-CONFIG_NCP_FS=m
-CONFIG_NCPFS_NFS_NS=y
-CONFIG_NCPFS_OS2_NS=y
-CONFIG_NCPFS_NLS=y
-CONFIG_NCPFS_EXTRAS=y
-CONFIG_CODA_FS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_DLM=m
-CONFIG_DLM_DEBUG=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRC16=m
-CONFIG_CRC7=m
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
+CONFIG_CRC32_SARWATE=y
diff --git a/arch/mips/configs/bcm63xx_defconfig b/arch/mips/configs/bcm63xx_defconfig
index 919005139f5..3fec26410f3 100644
--- a/arch/mips/configs/bcm63xx_defconfig
+++ b/arch/mips/configs/bcm63xx_defconfig
@@ -44,7 +44,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 5419adb219a..23b66934e18 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -19,7 +19,6 @@ CONFIG_INET=y
# CONFIG_IPV6 is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_JEDECPROBE=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
deleted file mode 100644
index bac26b971c5..00000000000
--- a/arch/mips/configs/db1000_defconfig
+++ /dev/null
@@ -1,359 +0,0 @@
-CONFIG_MIPS=y
-CONFIG_MIPS_ALCHEMY=y
-CONFIG_MIPS_DB1000=y
-CONFIG_SCHED_OMIT_FRAME_POINTER=y
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_HZ_100=y
-CONFIG_HZ=100
-CONFIG_PREEMPT_NONE=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_CROSS_COMPILE=""
-CONFIG_LOCALVERSION="-db1x00"
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_KERNEL_LZMA=y
-CONFIG_DEFAULT_HOSTNAME="db1x00"
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_FHANDLE=y
-CONFIG_AUDIT=y
-CONFIG_TINY_RCU=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_NAMESPACES=y
-CONFIG_UTS_NS=y
-CONFIG_IPC_NS=y
-CONFIG_USER_NS=y
-CONFIG_PID_NS=y
-CONFIG_NET_NS=y
-CONFIG_SYSCTL=y
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_AIO=y
-CONFIG_EMBEDDED=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_PERF_USE_VMALLOC=y
-CONFIG_PCI_QUIRKS=y
-CONFIG_SLAB=y
-CONFIG_SLABINFO=y
-CONFIG_BLOCK=y
-CONFIG_LBDAF=y
-CONFIG_BLK_DEV_BSG=y
-CONFIG_BLK_DEV_BSGLIB=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_DEFAULT_NOOP=y
-CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_FREEZER=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCCARD=y
-CONFIG_PCMCIA=y
-CONFIG_PCMCIA_LOAD_CIS=y
-CONFIG_PCMCIA_ALCHEMY_DEVBOARD=y
-CONFIG_BINFMT_ELF=y
-CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
-CONFIG_SUSPEND=y
-CONFIG_SUSPEND_FREEZER=y
-CONFIG_PM_SLEEP=y
-CONFIG_PM_RUNTIME=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_INET_TUNNEL=y
-CONFIG_INET_LRO=y
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_IPV6=y
-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
-CONFIG_INET6_XFRM_MODE_TUNNEL=y
-CONFIG_INET6_XFRM_MODE_BEET=y
-CONFIG_IPV6_SIT=y
-CONFIG_IPV6_NDISC_NODETYPE=y
-CONFIG_STP=y
-CONFIG_GARP=y
-CONFIG_BRIDGE=y
-CONFIG_BRIDGE_IGMP_SNOOPING=y
-CONFIG_VLAN_8021Q=y
-CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_LLC=y
-CONFIG_LLC2=y
-CONFIG_DNS_RESOLVER=y
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIBTUSB=y
-CONFIG_UEVENT_HELPER_PATH=""
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-CONFIG_MTD_CFI_I4=y
-CONFIG_MTD_CFI_I8=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_SCSI_MOD=y
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-CONFIG_SCSI_PROC_FS=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_ATA=y
-CONFIG_ATA_VERBOSE_ERROR=y
-CONFIG_ATA_SFF=y
-CONFIG_ATA_BMDMA=y
-CONFIG_PATA_HPT37X=y
-CONFIG_PATA_PCMCIA=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_FIREWIRE=y
-CONFIG_FIREWIRE_OHCI=y
-CONFIG_FIREWIRE_OHCI_DEBUG=y
-CONFIG_FIREWIRE_NET=y
-CONFIG_NETDEVICES=y
-CONFIG_MII=y
-CONFIG_PHYLIB=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MIPS_AU1X00_ENET=y
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=y
-CONFIG_PCMCIA_PCNET=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPP_MPPE=y
-CONFIG_PPPOE=y
-CONFIG_INPUT=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
-CONFIG_DEVKMEM=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_TTY_PRINTK=y
-CONFIG_DEVPORT=y
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_AU1100=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x16=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-CONFIG_SND_JACK=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_HRTIMER=y
-CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
-CONFIG_SND_DYNAMIC_MINORS=y
-CONFIG_SND_VMASTER=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_SOC=y
-CONFIG_SND_SOC_AC97_BUS=y
-CONFIG_SND_SOC_AU1XAUDIO=y
-CONFIG_SND_SOC_AU1XAC97C=y
-CONFIG_SND_SOC_DB1000=y
-CONFIG_SND_SOC_AC97_CODEC=y
-CONFIG_AC97_BUS=y
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-CONFIG_HIDRAW=y
-CONFIG_USB_HID=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-CONFIG_RTC_DRV_AU1XXX=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_USE_FOR_EXT23=y
-CONFIG_EXT4_FS_XATTR=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_JBD2=y
-CONFIG_FS_MBCACHE=y
-CONFIG_FS_POSIX_ACL=y
-CONFIG_EXPORTFS=y
-CONFIG_FILE_LOCKING=y
-CONFIG_FSNOTIFY=y
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY_USER=y
-CONFIG_GENERIC_ACL=y
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_MISC_FILESYSTEMS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_JFFS2_FS_POSIX_ACL=y
-CONFIG_JFFS2_FS_SECURITY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_LZO=y
-CONFIG_JFFS2_RTIME=y
-CONFIG_JFFS2_RUBIN=y
-CONFIG_JFFS2_CMODE_PRIORITY=y
-CONFIG_SQUASHFS=y
-CONFIG_SQUASHFS_ZLIB=y
-CONFIG_SQUASHFS_LZO=y
-CONFIG_SQUASHFS_XZ=y
-CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_PNFS_FILE_LAYOUT=y
-CONFIG_PNFS_BLOCK=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFS_USE_KERNEL_DNS=y
-CONFIG_NFS_USE_NEW_IDMAPPER=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-CONFIG_NFSD_V4=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_ACL_SUPPORT=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_SUNRPC_BACKCHANNEL=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_1250=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="noirqdebug rootwait root=/dev/sda1 rootfstype=ext4 console=ttyS0,115200 video=au1100fb:panel:CRT_800x600_16"
-CONFIG_DEBUG_ZBOOT=y
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-CONFIG_SECURITYFS=y
-CONFIG_DEFAULT_SECURITY_DAC=y
-CONFIG_DEFAULT_SECURITY=""
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_HASH2=y
-CONFIG_CRYPTO_RNG=y
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_PCOMP2=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
-CONFIG_CRYPTO_WORKQUEUE=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_ANSI_CPRNG=y
-CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_CRC_ITU_T=y
-CONFIG_CRC32=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_LZO_COMPRESS=y
-CONFIG_LZO_DECOMPRESS=y
-CONFIG_XZ_DEC=y
diff --git a/arch/mips/configs/db1235_defconfig b/arch/mips/configs/db1235_defconfig
deleted file mode 100644
index e2b4ad55462..00000000000
--- a/arch/mips/configs/db1235_defconfig
+++ /dev/null
@@ -1,435 +0,0 @@
-CONFIG_MIPS_ALCHEMY=y
-CONFIG_MIPS_DB1235=y
-CONFIG_COMPACTION=y
-CONFIG_KSM=y
-CONFIG_HZ_100=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCALVERSION="-db1235"
-CONFIG_KERNEL_LZMA=y
-CONFIG_DEFAULT_HOSTNAME="db1235"
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_FHANDLE=y
-CONFIG_TASKSTATS=y
-CONFIG_TASK_DELAY_ACCT=y
-CONFIG_AUDIT=y
-CONFIG_AUDIT_LOGINUID_IMMUTABLE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_NAMESPACES=y
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-CONFIG_JUMP_LABEL=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_LDM_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_PCI=y
-CONFIG_PCCARD=y
-CONFIG_PCMCIA_ALCHEMY_DEVBOARD=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_UNIX_DIAG=y
-CONFIG_XFRM_USER=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE_DEMUX=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_ARPD=y
-CONFIG_SYN_COOKIES=y
-CONFIG_NET_IPVTI=y
-CONFIG_INET_AH=y
-CONFIG_INET_ESP=y
-CONFIG_INET_IPCOMP=y
-CONFIG_INET_UDP_DIAG=y
-CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_TCP_CONG_HSTCP=y
-CONFIG_TCP_CONG_HYBLA=y
-CONFIG_TCP_CONG_SCALABLE=y
-CONFIG_TCP_CONG_LP=y
-CONFIG_TCP_CONG_VENO=y
-CONFIG_TCP_CONG_YEAH=y
-CONFIG_TCP_CONG_ILLINOIS=y
-CONFIG_DEFAULT_HYBLA=y
-CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-CONFIG_IPV6_MIP6=y
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
-CONFIG_IPV6_SIT_6RD=y
-CONFIG_IPV6_TUNNEL=y
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_IPV6_MROUTE=y
-CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
-CONFIG_IPV6_PIMSM_V2=y
-CONFIG_NETFILTER=y
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CONNTRACK_TIMEOUT=y
-CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
-CONFIG_NF_CT_PROTO_UDPLITE=y
-CONFIG_NF_CONNTRACK_AMANDA=y
-CONFIG_NF_CONNTRACK_FTP=y
-CONFIG_NF_CONNTRACK_H323=y
-CONFIG_NF_CONNTRACK_IRC=y
-CONFIG_NF_CONNTRACK_NETBIOS_NS=y
-CONFIG_NF_CONNTRACK_SNMP=y
-CONFIG_NF_CONNTRACK_PPTP=y
-CONFIG_NF_CONNTRACK_SANE=y
-CONFIG_NF_CONNTRACK_SIP=y
-CONFIG_NF_CONNTRACK_TFTP=y
-CONFIG_NF_CT_NETLINK=y
-CONFIG_NF_CT_NETLINK_TIMEOUT=y
-CONFIG_NF_CT_NETLINK_HELPER=y
-CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
-CONFIG_NETFILTER_XT_TARGET_HMARK=y
-CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
-CONFIG_NETFILTER_XT_TARGET_LED=y
-CONFIG_NETFILTER_XT_TARGET_LOG=y
-CONFIG_NETFILTER_XT_TARGET_MARK=y
-CONFIG_NETFILTER_XT_TARGET_NFLOG=y
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_TARGET_TEE=y
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
-CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
-CONFIG_NETFILTER_XT_MATCH_CLUSTER=y
-CONFIG_NETFILTER_XT_MATCH_COMMENT=y
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
-CONFIG_NETFILTER_XT_MATCH_CPU=y
-CONFIG_NETFILTER_XT_MATCH_DCCP=y
-CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y
-CONFIG_NETFILTER_XT_MATCH_DSCP=y
-CONFIG_NETFILTER_XT_MATCH_ESP=y
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_HELPER=y
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
-CONFIG_NETFILTER_XT_MATCH_LENGTH=y
-CONFIG_NETFILTER_XT_MATCH_LIMIT=y
-CONFIG_NETFILTER_XT_MATCH_MAC=y
-CONFIG_NETFILTER_XT_MATCH_MARK=y
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_NFACCT=y
-CONFIG_NETFILTER_XT_MATCH_OSF=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
-CONFIG_NETFILTER_XT_MATCH_POLICY=y
-CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA=y
-CONFIG_NETFILTER_XT_MATCH_RATEEST=y
-CONFIG_NETFILTER_XT_MATCH_REALM=y
-CONFIG_NETFILTER_XT_MATCH_RECENT=y
-CONFIG_NETFILTER_XT_MATCH_SCTP=y
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
-CONFIG_NETFILTER_XT_MATCH_STRING=y
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
-CONFIG_NETFILTER_XT_MATCH_TIME=y
-CONFIG_NETFILTER_XT_MATCH_U32=y
-CONFIG_NF_CONNTRACK_IPV4=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_AH=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_RPFILTER=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_NF_NAT=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_CLUSTERIP=y
-CONFIG_IP_NF_TARGET_ECN=y
-CONFIG_IP_NF_TARGET_TTL=y
-CONFIG_IP_NF_RAW=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=y
-CONFIG_NF_CONNTRACK_IPV6=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_MATCH_AH=y
-CONFIG_IP6_NF_MATCH_EUI64=y
-CONFIG_IP6_NF_MATCH_FRAG=y
-CONFIG_IP6_NF_MATCH_OPTS=y
-CONFIG_IP6_NF_MATCH_HL=y
-CONFIG_IP6_NF_MATCH_IPV6HEADER=y
-CONFIG_IP6_NF_MATCH_MH=y
-CONFIG_IP6_NF_MATCH_RPFILTER=y
-CONFIG_IP6_NF_MATCH_RT=y
-CONFIG_IP6_NF_TARGET_HL=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_IP6_NF_TARGET_REJECT=y
-CONFIG_IP6_NF_MANGLE=y
-CONFIG_IP6_NF_RAW=y
-CONFIG_BRIDGE_NF_EBTABLES=y
-CONFIG_BRIDGE_EBT_BROUTE=y
-CONFIG_BRIDGE_EBT_T_FILTER=y
-CONFIG_BRIDGE_EBT_T_NAT=y
-CONFIG_BRIDGE_EBT_802_3=y
-CONFIG_BRIDGE_EBT_AMONG=y
-CONFIG_BRIDGE_EBT_ARP=y
-CONFIG_BRIDGE_EBT_IP=y
-CONFIG_BRIDGE_EBT_IP6=y
-CONFIG_BRIDGE_EBT_LIMIT=y
-CONFIG_BRIDGE_EBT_MARK=y
-CONFIG_BRIDGE_EBT_PKTTYPE=y
-CONFIG_BRIDGE_EBT_STP=y
-CONFIG_BRIDGE_EBT_VLAN=y
-CONFIG_BRIDGE_EBT_ARPREPLY=y
-CONFIG_BRIDGE_EBT_DNAT=y
-CONFIG_BRIDGE_EBT_MARK_T=y
-CONFIG_BRIDGE_EBT_REDIRECT=y
-CONFIG_BRIDGE_EBT_SNAT=y
-CONFIG_BRIDGE_EBT_LOG=y
-CONFIG_BRIDGE_EBT_NFLOG=y
-CONFIG_L2TP=y
-CONFIG_L2TP_V3=y
-CONFIG_L2TP_IP=y
-CONFIG_L2TP_ETH=y
-CONFIG_BRIDGE=y
-CONFIG_VLAN_8021Q=y
-CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_LLC2=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=y
-CONFIG_NET_SCH_HTB=y
-CONFIG_NET_SCH_HFSC=y
-CONFIG_NET_SCH_PRIO=y
-CONFIG_NET_SCH_MULTIQ=y
-CONFIG_NET_SCH_RED=y
-CONFIG_NET_SCH_SFB=y
-CONFIG_NET_SCH_SFQ=y
-CONFIG_NET_SCH_TEQL=y
-CONFIG_NET_SCH_TBF=y
-CONFIG_NET_SCH_GRED=y
-CONFIG_NET_SCH_DSMARK=y
-CONFIG_NET_SCH_NETEM=y
-CONFIG_NET_SCH_DRR=y
-CONFIG_NET_SCH_MQPRIO=y
-CONFIG_NET_SCH_CHOKE=y
-CONFIG_NET_SCH_QFQ=y
-CONFIG_NET_SCH_CODEL=y
-CONFIG_NET_SCH_FQ_CODEL=y
-CONFIG_NET_SCH_INGRESS=y
-CONFIG_NET_SCH_PLUG=y
-CONFIG_NET_CLS_BASIC=y
-CONFIG_NET_CLS_TCINDEX=y
-CONFIG_NET_CLS_ROUTE4=y
-CONFIG_NET_CLS_FW=y
-CONFIG_NET_CLS_U32=y
-CONFIG_CLS_U32_PERF=y
-CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_RSVP=y
-CONFIG_NET_CLS_RSVP6=y
-CONFIG_NET_CLS_FLOW=y
-CONFIG_NET_EMATCH=y
-CONFIG_NET_EMATCH_CMP=y
-CONFIG_NET_EMATCH_NBYTE=y
-CONFIG_NET_EMATCH_U32=y
-CONFIG_NET_EMATCH_META=y
-CONFIG_NET_EMATCH_TEXT=y
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=y
-CONFIG_NET_ACT_GACT=y
-CONFIG_GACT_PROB=y
-CONFIG_NET_ACT_MIRRED=y
-CONFIG_NET_ACT_NAT=y
-CONFIG_NET_ACT_PEDIT=y
-CONFIG_NET_ACT_SIMP=y
-CONFIG_NET_ACT_SKBEDIT=y
-CONFIG_NET_ACT_CSUM=y
-CONFIG_NET_CLS_IND=y
-CONFIG_BT=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIBTUSB=y
-CONFIG_CFG80211=y
-CONFIG_CFG80211_CERTIFICATION_ONUS=y
-CONFIG_CFG80211_WEXT=y
-CONFIG_MAC80211=y
-CONFIG_MAC80211_LEDS=y
-CONFIG_RFKILL=y
-CONFIG_RFKILL_INPUT=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_PLATFORM=y
-CONFIG_EEPROM_AT24=y
-CONFIG_EEPROM_AT25=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE_AU1XXX=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_ATA=y
-CONFIG_PATA_HPT37X=y
-CONFIG_PATA_PCMCIA=y
-CONFIG_PATA_PLATFORM=y
-CONFIG_NETDEVICES=y
-CONFIG_MIPS_AU1X00_ENET=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
-CONFIG_AMD_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_RT2X00=y
-CONFIG_RT73USB=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_WM97XX=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_TTY_PRINTK=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_AU1550=y
-CONFIG_SPI=y
-CONFIG_SPI_AU1550=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_SENSORS_ADM1025=y
-CONFIG_SENSORS_LM70=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_HRTIMER=y
-CONFIG_SND_DYNAMIC_MINORS=y
-CONFIG_SND_SOC=y
-CONFIG_SND_SOC_AU1XPSC=y
-CONFIG_SND_SOC_DB1200=y
-CONFIG_HIDRAW=y
-CONFIG_UHID=y
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=y
-CONFIG_USB_DYNAMIC_MINORS=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_CLKGATE=y
-CONFIG_MMC_AU1X=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AU1XXX=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_XFS_FS=y
-CONFIG_XFS_POSIX_ACL=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CONFIGFS_FS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_LZO=y
-CONFIG_JFFS2_CMODE_FAVOURLZO=y
-CONFIG_SQUASHFS=y
-CONFIG_SQUASHFS_LZO=y
-CONFIG_SQUASHFS_XZ=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3_ACL=y
-CONFIG_NFSD_V4=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_CODEPAGE_1250=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_STRIP_ASM_SYMS=y
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_USER=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_CRYPTD=y
-CONFIG_CRYPTO_CCM=y
-CONFIG_CRYPTO_GCM=y
-CONFIG_CRYPTO_CTS=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_XTS=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_VMAC=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_RMD128=y
-CONFIG_CRYPTO_RMD160=y
-CONFIG_CRYPTO_RMD256=y
-CONFIG_CRYPTO_RMD320=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_CAMELLIA=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_SALSA20=y
-CONFIG_CRYPTO_SEED=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_ZLIB=y
-CONFIG_CRYPTO_LZO=y
-CONFIG_CRYPTO_USER_API_HASH=y
-CONFIG_CRYPTO_USER_API_SKCIPHER=y
diff --git a/arch/mips/configs/db1xxx_defconfig b/arch/mips/configs/db1xxx_defconfig
new file mode 100644
index 00000000000..a64b30b96a0
--- /dev/null
+++ b/arch/mips/configs/db1xxx_defconfig
@@ -0,0 +1,246 @@
+CONFIG_MIPS_ALCHEMY=y
+CONFIG_MIPS_DB1XXX=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUG=y
+CONFIG_HZ_100=y
+CONFIG_LOCALVERSION="-db1xxx"
+CONFIG_KERNEL_XZ=y
+CONFIG_DEFAULT_HOSTNAME="db1xxx"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_DEFAULT_NOOP=y
+CONFIG_PCI=y
+CONFIG_PCI_REALLOC_ENABLE_AUTO=y
+CONFIG_PCCARD=y
+CONFIG_PCMCIA_ALCHEMY_DEVBOARD=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_FIB_TRIE_STATS=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_VENO=y
+CONFIG_DEFAULT_VENO=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+CONFIG_IPV6_VTI=y
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_BRIDGE=y
+CONFIG_NETLINK_MMAP=y
+CONFIG_NETLINK_DIAG=y
+CONFIG_IRDA=y
+CONFIG_IRLAN=y
+CONFIG_IRCOMM=y
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_AU1000_FIR=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIBTUSB=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SST25L=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC_BCH=y
+CONFIG_MTD_NAND_AU1550=y
+CONFIG_MTD_NAND_PLATFORM=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_PATA_HPT37X=y
+CONFIG_PATA_HPT3X2N=y
+CONFIG_PATA_PCMCIA=y
+CONFIG_PATA_PLATFORM=y
+CONFIG_NETDEVICES=y
+CONFIG_NLMON=y
+CONFIG_PCMCIA_3C589=y
+CONFIG_MIPS_AU1X00_ENET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+CONFIG_AMD_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+CONFIG_TOUCHSCREEN_WM97XX=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_TTY_PRINTK=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_AU1550=y
+CONFIG_SPI=y
+CONFIG_SPI_AU1550=y
+CONFIG_SPI_GPIO=y
+CONFIG_SENSORS_ADM1025=y
+CONFIG_SENSORS_LM70=y
+CONFIG_FB=y
+CONFIG_FB_AU1100=y
+CONFIG_FB_AU1200=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_HRTIMER=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=1
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_AU1XPSC=y
+CONFIG_SND_SOC_AU1XAUDIO=y
+CONFIG_SND_SOC_DB1000=y
+CONFIG_SND_SOC_DB1200=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_OTG=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_AU1X=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AU1XXX=y
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_XFS_FS=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_FANOTIFY=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="local"
+CONFIG_NFS_V4_1_MIGRATION=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_CRYPTD=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRC32_SLICEBY4=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig
index e5b73de08fc..002680648dc 100644
--- a/arch/mips/configs/fuloong2e_defconfig
+++ b/arch/mips/configs/fuloong2e_defconfig
@@ -188,7 +188,6 @@ CONFIG_USB_KBD=y
CONFIG_USB_MOUSE=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OTG_WHITELIST=y
CONFIG_USB_WUSB_CBAF=m
diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig
index fb64589015f..8f219dac959 100644
--- a/arch/mips/configs/gpr_defconfig
+++ b/arch/mips/configs/gpr_defconfig
@@ -165,7 +165,6 @@ CONFIG_YAM=m
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index db5705e18b3..9bc08f27512 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -22,7 +22,6 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_CFI=y
diff --git a/arch/mips/configs/lasat_defconfig b/arch/mips/configs/lasat_defconfig
index d9f3db29ab9..0179c7fa014 100644
--- a/arch/mips/configs/lasat_defconfig
+++ b/arch/mips/configs/lasat_defconfig
@@ -31,7 +31,6 @@ CONFIG_INET=y
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
index 343bebc4b63..227a9de3224 100644
--- a/arch/mips/configs/lemote2f_defconfig
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -297,7 +297,6 @@ CONFIG_HID_WACOM=m
CONFIG_HID_ZEROPLUS=m
CONFIG_ZEROPLUS_FF=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_OTG_WHITELIST=y
diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
new file mode 100644
index 00000000000..ea1761f0f91
--- /dev/null
+++ b/arch/mips/configs/loongson3_defconfig
@@ -0,0 +1,362 @@
+CONFIG_MACH_LOONGSON=y
+CONFIG_SWIOTLB=y
+CONFIG_LEMOTE_MACH3A=y
+CONFIG_CPU_LOONGSON3=y
+CONFIG_64BIT=y
+CONFIG_PAGE_SIZE_16KB=y
+CONFIG_KSM=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HZ_256=y
+CONFIG_PREEMPT=y
+CONFIG_KEXEC=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZMA=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CPUSETS=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_PCI=y
+CONFIG_HT_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=y
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEASPM_PERFORMANCE=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_BINFMT_MISC=m
+CONFIG_MIPS32_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_IP_VS=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_SCTP=m
+CONFIG_L2TP=m
+CONFIG_BRIDGE=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_RFKILL=m
+CONFIG_RFKILL_INPUT=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=m
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_ISCSI_TCP=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=y
+CONFIG_MEGARAID_MAILBOX=y
+CONFIG_MEGARAID_LEGACY=y
+CONFIG_MEGARAID_SAS=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_PATA_ATIIXP=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_LOOPBACK_TARGET=m
+CONFIG_ISCSI_TARGET=m
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_IGB=y
+CONFIG_IXGB=y
+CONFIG_IXGBE=y
+# CONFIG_NET_VENDOR_I825XX is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_R8169=y
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_ATH_CARDS=m
+CONFIG_ATH9K=m
+CONFIG_HOSTAP=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_SPARSEKMAP=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_MOUSE_PS2_SENTELIC=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_RAW=m
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_HW_RANDOM=y
+CONFIG_RAW_DRIVER=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PIIX4=y
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_DRM=y
+CONFIG_DRM_RADEON=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB_RADEON=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=m
+CONFIG_BACKLIGHT_GENERIC=m
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+# CONFIG_SND_ISA is not set
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_PATCH_LOADER=y
+CONFIG_SND_HDA_CODEC_REALTEK=m
+CONFIG_SND_HDA_CODEC_CONEXANT=m
+# CONFIG_SND_USB is not set
+CONFIG_HID_A4TECH=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_DMADEVICES=y
+CONFIG_PM_DEVFREQ=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_DEVFREQ_GOV_PERFORMANCE=y
+CONFIG_DEVFREQ_GOV_POWERSAVE=y
+CONFIG_DEVFREQ_GOV_USERSPACE=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_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_QUOTA=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=936
+CONFIG_FAT_DEFAULT_IOCHARSET="gb2312"
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_CIFS=m
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_FRAME_WARN=1024
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_RCU_CPU_STALL_VERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PATH=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index ce1d3eeeb73..b745b6a9f32 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,9 @@
CONFIG_MIPS_MALTA=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32_R2=y
+CONFIG_PAGE_SIZE_16KB=y
CONFIG_MIPS_MT_SMP=y
+CONFIG_NR_CPUS=8
CONFIG_HZ_100=y
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
@@ -42,7 +44,6 @@ CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -68,7 +69,6 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
@@ -125,7 +125,6 @@ CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
@@ -185,7 +184,6 @@ CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
CONFIG_PHONET=m
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
@@ -226,9 +224,9 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
CONFIG_MAC80211_MESH=y
CONFIG_RFKILL=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_CONNECTOR=m
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_OOPS=m
CONFIG_MTD_CFI=y
@@ -328,7 +326,6 @@ CONFIG_LIBERTAS=m
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_HWMON is not set
diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig
index 341bb47204d..4f7d952d851 100644
--- a/arch/mips/configs/malta_kvm_defconfig
+++ b/arch/mips/configs/malta_kvm_defconfig
@@ -3,6 +3,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32_R2=y
CONFIG_PAGE_SIZE_16KB=y
CONFIG_MIPS_MT_SMP=y
+CONFIG_NR_CPUS=8
CONFIG_HZ_100=y
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
@@ -44,7 +45,6 @@ CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -70,7 +70,6 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
@@ -127,7 +126,6 @@ CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
@@ -187,7 +185,6 @@ CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
CONFIG_PHONET=m
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
@@ -228,9 +225,9 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
CONFIG_MAC80211_MESH=y
CONFIG_RFKILL=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_CONNECTOR=m
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_OOPS=m
CONFIG_MTD_CFI=y
@@ -300,6 +297,7 @@ CONFIG_IFB=m
CONFIG_MACVLAN=m
CONFIG_TUN=m
CONFIG_VETH=m
+CONFIG_VHOST_NET=m
CONFIG_PCNET32=y
CONFIG_CHELSIO_T3=m
CONFIG_AX88796=m
@@ -329,7 +327,6 @@ CONFIG_LIBERTAS=m
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_HWMON is not set
@@ -453,4 +450,3 @@ CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_KVM_MIPS_DYN_TRANS=y
CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS=y
-CONFIG_VHOST_NET=m
diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig
index 2b8558b7108..e36681c24dd 100644
--- a/arch/mips/configs/malta_kvm_guest_defconfig
+++ b/arch/mips/configs/malta_kvm_guest_defconfig
@@ -44,7 +44,6 @@ CONFIG_INET_IPCOMP=m
CONFIG_INET_XFRM_MODE_TRANSPORT=m
CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -70,7 +69,6 @@ CONFIG_NF_CONNTRACK_SANE=m
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
@@ -127,7 +125,6 @@ CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
@@ -187,7 +184,6 @@ CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
CONFIG_PHONET=m
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
@@ -228,9 +224,9 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
CONFIG_MAC80211_MESH=y
CONFIG_RFKILL=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
CONFIG_CONNECTOR=m
CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_OOPS=m
CONFIG_MTD_CFI=y
@@ -331,7 +327,6 @@ CONFIG_LIBERTAS=m
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_HWMON is not set
diff --git a/arch/mips/configs/maltaaprp_defconfig b/arch/mips/configs/maltaaprp_defconfig
index 93057a760df..fb042ce86b4 100644
--- a/arch/mips/configs/maltaaprp_defconfig
+++ b/arch/mips/configs/maltaaprp_defconfig
@@ -44,7 +44,6 @@ CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
# CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
@@ -55,7 +54,6 @@ CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
@@ -80,6 +78,7 @@ CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_CLS_IND=y
# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_IDE=y
diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig
index 8a666021b87..f8a32315bb3 100644
--- a/arch/mips/configs/maltasmvp_defconfig
+++ b/arch/mips/configs/maltasmvp_defconfig
@@ -1,12 +1,12 @@
CONFIG_MIPS_MALTA=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32_R2=y
+CONFIG_PAGE_SIZE_16KB=y
CONFIG_MIPS_MT_SMP=y
CONFIG_SCHED_SMT=y
-CONFIG_MIPS_CMP=y
+CONFIG_MIPS_CPS=y
CONFIG_NR_CPUS=8
CONFIG_HZ_100=y
-CONFIG_LOCALVERSION="cmp"
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
@@ -47,7 +47,6 @@ CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
# CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
@@ -58,7 +57,6 @@ CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
@@ -83,6 +81,7 @@ CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_CLS_IND=y
# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_IDE=y
diff --git a/arch/mips/configs/maltasmtc_defconfig b/arch/mips/configs/maltasmvp_eva_defconfig
index 4e54b75d89b..c83338a3991 100644
--- a/arch/mips/configs/maltasmtc_defconfig
+++ b/arch/mips/configs/maltasmvp_eva_defconfig
@@ -1,14 +1,17 @@
CONFIG_MIPS_MALTA=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32_R2=y
-CONFIG_MIPS_MT_SMTC=y
-# CONFIG_MIPS_MT_FPAFF is not set
-CONFIG_NR_CPUS=9
-CONFIG_HZ_48=y
-CONFIG_LOCALVERSION="smtc"
+CONFIG_CPU_MIPS32_3_5_FEATURES=y
+CONFIG_PAGE_SIZE_16KB=y
+CONFIG_MIPS_MT_SMP=y
+CONFIG_SCHED_SMT=y
+CONFIG_MIPS_CPS=y
+CONFIG_NR_CPUS=8
+CONFIG_HZ_100=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=15
@@ -45,7 +48,6 @@ CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
# CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
@@ -56,7 +58,6 @@ CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
@@ -81,6 +82,7 @@ CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_CLS_IND=y
# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_IDE=y
@@ -129,9 +131,10 @@ CONFIG_PCNET32=y
# CONFIG_NET_VENDOR_TI is not set
# CONFIG_NET_VENDOR_TOSHIBA is not set
# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_WLAN is not set
# CONFIG_VT is not set
-CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_LEGACY_PTY_COUNT=4
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_HW_RANDOM=y
diff --git a/arch/mips/configs/maltaup_defconfig b/arch/mips/configs/maltaup_defconfig
index 9868fc9c113..62344648eb7 100644
--- a/arch/mips/configs/maltaup_defconfig
+++ b/arch/mips/configs/maltaup_defconfig
@@ -43,7 +43,6 @@ CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
# CONFIG_INET_LRO is not set
-CONFIG_IPV6_PRIVACY=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
@@ -54,7 +53,6 @@ CONFIG_ATALK=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
@@ -79,6 +77,7 @@ CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_CLS_IND=y
# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_IDE=y
diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig
index 636f82b89fd..4c2c0c4b9bb 100644
--- a/arch/mips/configs/markeins_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -124,7 +124,6 @@ CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_RAW=m
CONFIG_FW_LOADER=m
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
diff --git a/arch/mips/configs/mips_paravirt_defconfig b/arch/mips/configs/mips_paravirt_defconfig
new file mode 100644
index 00000000000..84cfcb4bf2e
--- /dev/null
+++ b/arch/mips/configs/mips_paravirt_defconfig
@@ -0,0 +1,103 @@
+CONFIG_MIPS_PARAVIRT=y
+CONFIG_CPU_MIPS64_R2=y
+CONFIG_64BIT=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_SMP=y
+CONFIG_HZ_1000=y
+CONFIG_PREEMPT=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PCI=y
+CONFIG_MIPS32_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_VIRTIO_NET=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# 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_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_MARVELL_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_BCM87XX_PHY=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index c16de981292..7a346605c49 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -47,7 +47,6 @@ CONFIG_GPIO_VR41XX=y
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_OHCI_HCD=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_VR41XX=y
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig
index d1142e9cd9a..201edfb2637 100644
--- a/arch/mips/configs/msp71xx_defconfig
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -67,7 +67,6 @@ CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PMCMSP=y
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 9fa8f16068d..d269a5326a3 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -246,7 +246,6 @@ CONFIG_BT_HCIBTUART=m
CONFIG_BT_HCIVHCI=m
CONFIG_CONNECTOR=m
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
@@ -576,7 +575,6 @@ CONFIG_USB_HIDDEV=y
CONFIG_USB_KBD=m
CONFIG_USB_MOUSE=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ROOT_HUB_TT=y
diff --git a/arch/mips/configs/pnx8335_stb225_defconfig b/arch/mips/configs/pnx8335_stb225_defconfig
index f2925769dfa..c887066ecc2 100644
--- a/arch/mips/configs/pnx8335_stb225_defconfig
+++ b/arch/mips/configs/pnx8335_stb225_defconfig
@@ -31,7 +31,6 @@ CONFIG_INET_AH=y
# CONFIG_IPV6 is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
diff --git a/arch/mips/configs/powertv_defconfig b/arch/mips/configs/powertv_defconfig
deleted file mode 100644
index 7fda0ce5f69..00000000000
--- a/arch/mips/configs/powertv_defconfig
+++ /dev/null
@@ -1,136 +0,0 @@
-CONFIG_POWERTV=y
-CONFIG_BOOTLOADER_FAMILY="R2"
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_HZ_1000=y
-CONFIG_PREEMPT=y
-# CONFIG_SECCOMP is not set
-CONFIG_EXPERIMENTAL=y
-CONFIG_CROSS_COMPILE=""
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS_ALL=y
-# CONFIG_PCSPKR_PLATFORM is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_SLUB_DEBUG is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_PNP=y
-CONFIG_SYN_COOKIES=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=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-CONFIG_IPV6_TUNNEL=y
-CONFIG_NETFILTER=y
-# CONFIG_BRIDGE_NETFILTER is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_BRIDGE=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_TBF=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_WLAN is not set
-CONFIG_USB_RTL8150=y
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-# CONFIG_VGA_ARB is not set
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_CONSOLE=y
-CONFIG_USB_SERIAL_CP210X=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_FUSE_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_EARLY_PRINTK is not set
-CONFIG_CMDLINE_BOOL=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
new file mode 100644
index 00000000000..2b965470c35
--- /dev/null
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -0,0 +1,188 @@
+CONFIG_MACH_JZ4740=y
+# CONFIG_COMPACTION is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_HZ_100=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+CONFIG_TCP_CONG_WESTWOOD=y
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_JZ4740=y
+CONFIG_MTD_UBI=y
+CONFIG_NETDEVICES=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_MATRIX=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=2
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_DMA is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_JZ4740=y
+CONFIG_CHARGER_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_MFD_JZ4740_ADC=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_JZ4740=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_MIPS is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_JZ4740_SOC=y
+CONFIG_SND_JZ4740_SOC_QI_LB60=y
+CONFIG_USB=y
+CONFIG_USB_OTG_BLACKLIST_HUB=y
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_JZ4740=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_ETH=y
+# CONFIG_USB_ETH_RNDIS is not set
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_JZ4740=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_JZ4740=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_JZ4740=y
+CONFIG_PWM=y
+CONFIG_PWM_JZ4740=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+# CONFIG_JFFS2_ZLIB is not set
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_READABLE_ASM=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_FTRACE is not set
+CONFIG_KGDB=y
+CONFIG_RUNTIME_DEBUG=y
+CONFIG_CRYPTO_ZLIB=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_FONTS=y
+CONFIG_FONT_SUN8x16=y
diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig
index b85b121397c..5d9d708e12e 100644
--- a/arch/mips/configs/rb532_defconfig
+++ b/arch/mips/configs/rb532_defconfig
@@ -114,7 +114,6 @@ CONFIG_NET_CLS_IND=y
CONFIG_HAMRADIO=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_BLOCK2MTD=y
diff --git a/arch/mips/configs/rbtx49xx_defconfig b/arch/mips/configs/rbtx49xx_defconfig
index 9cba856277f..f8bf9b4c134 100644
--- a/arch/mips/configs/rbtx49xx_defconfig
+++ b/arch/mips/configs/rbtx49xx_defconfig
@@ -35,7 +35,6 @@ CONFIG_IP_PNP=y
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=m
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 59d9d2fdcd4..73e7bf49461 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -301,7 +301,6 @@ CONFIG_USB_HIDDEV=y
CONFIG_USB_KBD=m
CONFIG_USB_MOUSE=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
diff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfig
index d1741bcf894..d14ae2fa7d1 100644
--- a/arch/mips/configs/rt305x_defconfig
+++ b/arch/mips/configs/rt305x_defconfig
@@ -81,7 +81,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_AMDSTD=y
@@ -89,6 +88,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_M25P80=y
+CONFIG_MTD_SPI_NOR=y
CONFIG_EEPROM_93CX6=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig
index 5b0463ef938..51bab13ef6f 100644
--- a/arch/mips/configs/sb1250_swarm_defconfig
+++ b/arch/mips/configs/sb1250_swarm_defconfig
@@ -72,7 +72,6 @@ CONFIG_SERIO_RAW=m
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_EXT2_FS=y
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index 30036b4cbeb..11f51505d56 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -72,7 +72,6 @@ CONFIG_GPIO_TB0219=y
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index 81bfa1d4d8e..d99b1905a1b 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -69,7 +69,6 @@ CONFIG_SERIAL_VR41XX_CONSOLE=y
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile
index 3d5d2c56de8..bd74e05c90b 100644
--- a/arch/mips/dec/Makefile
+++ b/arch/mips/dec/Makefile
@@ -3,7 +3,7 @@
#
obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \
- kn02-irq.o kn02xa-berr.o reset.o setup.o time.o
+ kn02-irq.o kn02xa-berr.o platform.o reset.o setup.o time.o
obj-$(CONFIG_TC) += tc.o
obj-$(CONFIG_CPU_HAS_WB) += wbflush.o
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
index 5abf4e89421..2a66e908f6a 100644
--- a/arch/mips/dec/ecc-berr.c
+++ b/arch/mips/dec/ecc-berr.c
@@ -21,6 +21,7 @@
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
+#include <asm/cpu-type.h>
#include <asm/irq_regs.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 22afed16ccd..41a2fa1fa12 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -118,7 +118,7 @@
* 7 FPU/R4k timer
*
* We handle the IRQ according to _our_ priority (see setup.c),
- * then we just return. If multiple IRQs are pending then we will
+ * then we just return. If multiple IRQs are pending then we will
* just take another exception, big deal.
*/
.align 5
@@ -146,7 +146,7 @@
/*
* Find irq with highest priority
*/
- PTR_LA t1,cpu_mask_nr_tbl
+ PTR_LA t1,cpu_mask_nr_tbl
1: lw t2,(t1)
nop
and t2,t0
@@ -195,7 +195,7 @@
/*
* Find irq with highest priority
*/
- PTR_LA t1,asic_mask_nr_tbl
+ PTR_LA t1,asic_mask_nr_tbl
2: lw t2,(t1)
nop
and t2,t0
@@ -221,7 +221,7 @@
FEXPORT(cpu_all_int) # HALT, timers, software junk
li a0,DEC_CPU_IRQ_BASE
srl t0,CAUSEB_IP
- li t1,CAUSEF_IP>>CAUSEB_IP # mask
+ li t1,CAUSEF_IP>>CAUSEB_IP # mask
b 1f
li t2,4 # nr of bits / 2
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
index 4b3e3a4375a..e04d973ce5a 100644
--- a/arch/mips/dec/ioasic-irq.c
+++ b/arch/mips/dec/ioasic-irq.c
@@ -1,7 +1,7 @@
/*
* DEC I/O ASIC interrupts.
*
- * Copyright (c) 2002, 2003 Maciej W. Rozycki
+ * Copyright (c) 2002, 2003, 2013 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -51,22 +51,51 @@ static struct irq_chip ioasic_irq_type = {
.irq_unmask = unmask_ioasic_irq,
};
-void clear_ioasic_dma_irq(unsigned int irq)
+static void clear_ioasic_dma_irq(struct irq_data *d)
{
u32 sir;
- sir = ~(1 << (irq - ioasic_irq_base));
+ sir = ~(1 << (d->irq - ioasic_irq_base));
ioasic_write(IO_REG_SIR, sir);
+ fast_iob();
}
static struct irq_chip ioasic_dma_irq_type = {
.name = "IO-ASIC-DMA",
- .irq_ack = ack_ioasic_irq,
+ .irq_ack = clear_ioasic_dma_irq,
.irq_mask = mask_ioasic_irq,
- .irq_mask_ack = ack_ioasic_irq,
.irq_unmask = unmask_ioasic_irq,
+ .irq_eoi = clear_ioasic_dma_irq,
};
+/*
+ * I/O ASIC implements two kinds of DMA interrupts, informational and
+ * error interrupts.
+ *
+ * The formers do not stop DMA and should be cleared as soon as possible
+ * so that if they retrigger before the handler has completed, usually as
+ * a side effect of actions taken by the handler, then they are reissued.
+ * These use the `handle_edge_irq' handler that clears the request right
+ * away.
+ *
+ * The latters stop DMA and do not resume it until the interrupt has been
+ * cleared. This cannot be done until after a corrective action has been
+ * taken and this also means they will not retrigger. Therefore they use
+ * the `handle_fasteoi_irq' handler that only clears the request on the
+ * way out. Because MIPS processor interrupt inputs, one of which the I/O
+ * ASIC is cascaded to, are level-triggered it is recommended that error
+ * DMA interrupt action handlers are registered with the IRQF_ONESHOT flag
+ * set so that they are run with the interrupt line masked.
+ *
+ * This mask has `1' bits in the positions of informational interrupts.
+ */
+#define IO_IRQ_DMA_INFO \
+ (IO_IRQ_MASK(IO_INR_SCC0A_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_SCC1A_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_ISDN_TXDMA) | \
+ IO_IRQ_MASK(IO_INR_ISDN_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_ASC_DMA))
+
void __init init_ioasic_irqs(int base)
{
int i;
@@ -79,7 +108,9 @@ void __init init_ioasic_irqs(int base)
irq_set_chip_and_handler(i, &ioasic_irq_type,
handle_level_irq);
for (; i < base + IO_IRQ_LINES; i++)
- irq_set_chip(i, &ioasic_dma_irq_type);
+ irq_set_chip_and_handler(i, &ioasic_dma_irq_type,
+ 1 << (i - base) & IO_IRQ_DMA_INFO ?
+ handle_edge_irq : handle_fasteoi_irq);
ioasic_irq_base = base;
}
diff --git a/arch/mips/dec/kn02xa-berr.c b/arch/mips/dec/kn02xa-berr.c
index f434b759e3b..ec606363b80 100644
--- a/arch/mips/dec/kn02xa-berr.c
+++ b/arch/mips/dec/kn02xa-berr.c
@@ -19,6 +19,7 @@
#include <linux/types.h>
#include <asm/addrspace.h>
+#include <asm/cpu-type.h>
#include <asm/irq_regs.h>
#include <asm/ptrace.h>
#include <asm/traps.h>
diff --git a/arch/mips/dec/platform.c b/arch/mips/dec/platform.c
new file mode 100644
index 00000000000..c7ac86af847
--- /dev/null
+++ b/arch/mips/dec/platform.c
@@ -0,0 +1,44 @@
+/*
+ * DEC platform devices.
+ *
+ * Copyright (c) 2014 Maciej W. Rozycki
+ *
+ * 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/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/platform_device.h>
+
+static struct resource dec_rtc_resources[] = {
+ {
+ .name = "rtc",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct cmos_rtc_board_info dec_rtc_info = {
+ .flags = CMOS_RTC_FLAGS_NOFREQ,
+ .address_space = 64,
+};
+
+static struct platform_device dec_rtc_device = {
+ .name = "rtc_cmos",
+ .id = PLATFORM_DEVID_NONE,
+ .dev.platform_data = &dec_rtc_info,
+ .resource = dec_rtc_resources,
+ .num_resources = ARRAY_SIZE(dec_rtc_resources),
+};
+
+static int __init dec_add_devices(void)
+{
+ dec_rtc_resources[0].start = RTC_PORT(0);
+ dec_rtc_resources[0].end = RTC_PORT(0) + dec_kn_slot_size - 1;
+ return platform_device_register(&dec_rtc_device);
+}
+
+device_initcall(dec_add_devices);
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
index 064ae7a76bd..ae73e42ac20 100644
--- a/arch/mips/dec/prom/Makefile
+++ b/arch/mips/dec/prom/Makefile
@@ -6,4 +6,3 @@
lib-y += init.o memory.o cmdline.o identify.o console.o
lib-$(CONFIG_32BIT) += locore.o
-lib-$(CONFIG_64BIT) += call_o32.o
diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S
deleted file mode 100644
index c0d1522d448..00000000000
--- a/arch/mips/dec/prom/call_o32.S
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * O32 interface for the 64 (or N32) ABI.
- *
- * Copyright (C) 2002 Maciej W. Rozycki
- *
- * 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/asm.h>
-#include <asm/regdef.h>
-
-/* Maximum number of arguments supported. Must be even! */
-#define O32_ARGC 32
-/* Number of static registers we save. */
-#define O32_STATC 11
-/* Frame size for both of the above. */
-#define O32_FRAMESZ (4 * O32_ARGC + SZREG * O32_STATC)
-
- .text
-
-/*
- * O32 function call dispatcher, for interfacing 32-bit ROM routines.
- *
- * The standard 64 (N32) calling sequence is supported, with a0
- * holding a function pointer, a1-a7 -- its first seven arguments
- * and the stack -- remaining ones (up to O32_ARGC, including a1-a7).
- * Static registers, gp and fp are preserved, v0 holds a result.
- * This code relies on the called o32 function for sp and ra
- * restoration and thus both this dispatcher and the current stack
- * have to be placed in a KSEGx (or KUSEG) address space. Any
- * pointers passed have to point to addresses within one of these
- * spaces as well.
- */
-NESTED(call_o32, O32_FRAMESZ, ra)
- REG_SUBU sp,O32_FRAMESZ
-
- REG_S ra,O32_FRAMESZ-1*SZREG(sp)
- REG_S fp,O32_FRAMESZ-2*SZREG(sp)
- REG_S gp,O32_FRAMESZ-3*SZREG(sp)
- REG_S s7,O32_FRAMESZ-4*SZREG(sp)
- REG_S s6,O32_FRAMESZ-5*SZREG(sp)
- REG_S s5,O32_FRAMESZ-6*SZREG(sp)
- REG_S s4,O32_FRAMESZ-7*SZREG(sp)
- REG_S s3,O32_FRAMESZ-8*SZREG(sp)
- REG_S s2,O32_FRAMESZ-9*SZREG(sp)
- REG_S s1,O32_FRAMESZ-10*SZREG(sp)
- REG_S s0,O32_FRAMESZ-11*SZREG(sp)
-
- move jp,a0
-
- sll a0,a1,zero
- sll a1,a2,zero
- sll a2,a3,zero
- sll a3,a4,zero
- sw a5,0x10(sp)
- sw a6,0x14(sp)
- sw a7,0x18(sp)
-
- PTR_LA t0,O32_FRAMESZ(sp)
- PTR_LA t1,0x1c(sp)
- li t2,O32_ARGC-7
-1:
- lw t3,(t0)
- REG_ADDU t0,SZREG
- sw t3,(t1)
- REG_SUBU t2,1
- REG_ADDU t1,4
- bnez t2,1b
-
- jalr jp
-
- REG_L s0,O32_FRAMESZ-11*SZREG(sp)
- REG_L s1,O32_FRAMESZ-10*SZREG(sp)
- REG_L s2,O32_FRAMESZ-9*SZREG(sp)
- REG_L s3,O32_FRAMESZ-8*SZREG(sp)
- REG_L s4,O32_FRAMESZ-7*SZREG(sp)
- REG_L s5,O32_FRAMESZ-6*SZREG(sp)
- REG_L s6,O32_FRAMESZ-5*SZREG(sp)
- REG_L s7,O32_FRAMESZ-4*SZREG(sp)
- REG_L gp,O32_FRAMESZ-3*SZREG(sp)
- REG_L fp,O32_FRAMESZ-2*SZREG(sp)
- REG_L ra,O32_FRAMESZ-1*SZREG(sp)
-
- REG_ADDU sp,O32_FRAMESZ
- jr ra
-END(call_o32)
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index ab169046e44..4e1761e0a09 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -13,6 +13,7 @@
#include <asm/bootinfo.h>
#include <asm/cpu.h>
+#include <asm/cpu-type.h>
#include <asm/processor.h>
#include <asm/dec/prom.h>
@@ -103,7 +104,7 @@ void __init prom_init(void)
if (prom_is_rex(magic))
rex_clear_cache();
- /* Register the early console. */
+ /* Register the early console. */
register_prom_console();
/* Were we compiled with the right CPU option? */
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
index 0aadac74290..8c62316f22f 100644
--- a/arch/mips/dec/prom/memory.c
+++ b/arch/mips/dec/prom/memory.c
@@ -22,7 +22,7 @@ volatile unsigned long mem_err; /* So we know an error occurred */
/*
* Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
- * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
+ * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
*/
#define CHUNK_SIZE 0x400000
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 741cb4235bd..41bbffd9cc0 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -23,6 +23,7 @@
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
#include <asm/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
@@ -65,7 +66,7 @@ EXPORT_SYMBOL(ioasic_base);
/*
* IRQ routing and priority tables. Priorites are set as follows:
*
- * KN01 KN230 KN02 KN02-BA KN02-CA KN03
+ * KN01 KN230 KN02 KN02-BA KN02-CA KN03
*
* MEMORY CPU CPU CPU ASIC CPU CPU
* RTC CPU CPU CPU ASIC CPU CPU
@@ -413,7 +414,7 @@ static void __init dec_init_kn02(void)
/*
* Machine-specific initialisation for KN02-BA, aka DS5000/1xx
- * (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka
+ * (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka
* DS5000/150, aka 4min.
*/
static int kn02ba_interrupt[DEC_NR_INTS] __initdata = {
@@ -748,6 +749,10 @@ void __init arch_init_irq(void)
cpu_fpu_mask = 0;
dec_interrupt[DEC_IRQ_FPU] = -1;
}
+ /* Free the halt interrupt unused on R4k systems. */
+ if (current_cpu_type() == CPU_R4000SC ||
+ current_cpu_type() == CPU_R4400SC)
+ dec_interrupt[DEC_IRQ_HALT] = -1;
/* Register board interrupts: FPU and cascade. */
if (dec_interrupt[DEC_IRQ_FPU] >= 0)
diff --git a/arch/mips/emma/markeins/setup.c b/arch/mips/emma/markeins/setup.c
index d71005835c0..9100122e5ce 100644
--- a/arch/mips/emma/markeins/setup.c
+++ b/arch/mips/emma/markeins/setup.c
@@ -111,9 +111,6 @@ void __init plat_mem_setup(void)
iomem_resource.start = EMMA2RH_IO_BASE;
iomem_resource.end = EMMA2RH_ROM_BASE - 1;
- /* Reboot on panic */
- panic_timeout = 180;
-
markeins_sio_setup();
}
diff --git a/arch/mips/fw/arc/file.c b/arch/mips/fw/arc/file.c
index a8b08032348..49fd3ff13fe 100644
--- a/arch/mips/fw/arc/file.c
+++ b/arch/mips/fw/arc/file.c
@@ -8,7 +8,6 @@
* Copyright (C) 1994, 1995, 1996, 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
-#include <linux/init.h>
#include <asm/fw/arc/types.h>
#include <asm/sgialib.h>
diff --git a/arch/mips/fw/lib/call_o32.S b/arch/mips/fw/lib/call_o32.S
index b308b2a0613..4703fe4dbd9 100644
--- a/arch/mips/fw/lib/call_o32.S
+++ b/arch/mips/fw/lib/call_o32.S
@@ -1,7 +1,7 @@
/*
* O32 interface for the 64 (or N32) ABI.
*
- * Copyright (C) 2002 Maciej W. Rozycki
+ * Copyright (C) 2002, 2014 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -12,28 +12,37 @@
#include <asm/asm.h>
#include <asm/regdef.h>
+/* O32 register size. */
+#define O32_SZREG 4
/* Maximum number of arguments supported. Must be even! */
#define O32_ARGC 32
-/* Number of static registers we save. */
+/* Number of static registers we save. */
#define O32_STATC 11
-/* Frame size for static register */
-#define O32_FRAMESZ (SZREG * O32_STATC)
-/* Frame size on new stack */
-#define O32_FRAMESZ_NEW (SZREG + 4 * O32_ARGC)
+/* Argument area frame size. */
+#define O32_ARGSZ (O32_SZREG * O32_ARGC)
+/* Static register save area frame size. */
+#define O32_STATSZ (SZREG * O32_STATC)
+/* Stack pointer register save area frame size. */
+#define O32_SPSZ SZREG
+/* Combined area frame size. */
+#define O32_FRAMESZ (O32_ARGSZ + O32_SPSZ + O32_STATSZ)
+/* Switched stack frame size. */
+#define O32_NFRAMESZ (O32_ARGSZ + O32_SPSZ)
.text
/*
* O32 function call dispatcher, for interfacing 32-bit ROM routines.
*
- * The standard 64 (N32) calling sequence is supported, with a0
- * holding a function pointer, a1 a new stack pointer, a2-a7 -- its
- * first six arguments and the stack -- remaining ones (up to O32_ARGC,
- * including a2-a7). Static registers, gp and fp are preserved, v0 holds
- * a result. This code relies on the called o32 function for sp and ra
- * restoration and this dispatcher has to be placed in a KSEGx (or KUSEG)
- * address space. Any pointers passed have to point to addresses within
- * one of these spaces as well.
+ * The standard 64 (N32) calling sequence is supported, with a0 holding
+ * a function pointer, a1 a pointer to the new stack to call the
+ * function with or 0 if no stack switching is requested, a2-a7 -- the
+ * function call's first six arguments, and the stack -- the remaining
+ * arguments (up to O32_ARGC, including a2-a7). Static registers, gp
+ * and fp are preserved, v0 holds the result. This code relies on the
+ * called o32 function for sp and ra restoration and this dispatcher has
+ * to be placed in a KSEGx (or KUSEG) address space. Any pointers
+ * passed have to point to addresses within one of these spaces as well.
*/
NESTED(call_o32, O32_FRAMESZ, ra)
REG_SUBU sp,O32_FRAMESZ
@@ -51,32 +60,36 @@ NESTED(call_o32, O32_FRAMESZ, ra)
REG_S s0,O32_FRAMESZ-11*SZREG(sp)
move jp,a0
- REG_SUBU s0,a1,O32_FRAMESZ_NEW
- REG_S sp,O32_FRAMESZ_NEW-1*SZREG(s0)
+
+ move fp,sp
+ beqz a1,0f
+ REG_SUBU fp,a1,O32_NFRAMESZ
+0:
+ REG_S sp,O32_NFRAMESZ-1*SZREG(fp)
sll a0,a2,zero
sll a1,a3,zero
sll a2,a4,zero
sll a3,a5,zero
- sw a6,0x10(s0)
- sw a7,0x14(s0)
+ sw a6,4*O32_SZREG(fp)
+ sw a7,5*O32_SZREG(fp)
PTR_LA t0,O32_FRAMESZ(sp)
- PTR_LA t1,0x18(s0)
+ PTR_LA t1,6*O32_SZREG(fp)
li t2,O32_ARGC-6
1:
lw t3,(t0)
REG_ADDU t0,SZREG
sw t3,(t1)
REG_SUBU t2,1
- REG_ADDU t1,4
+ REG_ADDU t1,O32_SZREG
bnez t2,1b
- move sp,s0
+ move sp,fp
jalr jp
- REG_L sp,O32_FRAMESZ_NEW-1*SZREG(sp)
+ REG_L sp,O32_NFRAMESZ-1*SZREG(sp)
REG_L s0,O32_FRAMESZ-11*SZREG(sp)
REG_L s1,O32_FRAMESZ-10*SZREG(sp)
diff --git a/arch/mips/fw/sni/sniprom.c b/arch/mips/fw/sni/sniprom.c
index 2c2cb182af4..6aa264b9856 100644
--- a/arch/mips/fw/sni/sniprom.c
+++ b/arch/mips/fw/sni/sniprom.c
@@ -40,7 +40,8 @@
#ifdef CONFIG_64BIT
-static u8 o32_stk[16384];
+/* O32 stack has to be 8-byte aligned. */
+static u64 o32_stk[4096];
#define O32_STK &o32_stk[sizeof(o32_stk)]
#define __PROM_O32(fun, arg) fun arg __asm__(#fun); \
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 454ddf9bb76..05439187891 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -2,10 +2,13 @@
generic-y += cputime.h
generic-y += current.h
generic-y += emergency-restart.h
+generic-y += hash.h
generic-y += local64.h
+generic-y += mcs_spinlock.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
diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
index 13d61c002e4..3f745459fdb 100644
--- a/arch/mips/include/asm/addrspace.h
+++ b/arch/mips/include/asm/addrspace.h
@@ -58,7 +58,7 @@
/*
* Memory segments (64bit kernel mode addresses)
- * The compatibility segments use the full 64-bit sign extended value. Note
+ * The compatibility segments use the full 64-bit sign extended value. Note
* the R8000 doesn't have them so don't reference these in generic MIPS code.
*/
#define XKUSEG _CONST64_(0x0000000000000000)
@@ -131,7 +131,7 @@
/*
* The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting
- * the region, 3 bits for the CCA mode. This leaves 59 bits of which the
+ * the region, 3 bits for the CCA mode. This leaves 59 bits of which the
* R8000 implements most with its 48-bit physical address space.
*/
#define TO_PHYS_MASK _CONST64_(0x07ffffffffffffff) /* 2^^59 - 1 */
diff --git a/arch/mips/include/asm/amon.h b/arch/mips/include/asm/amon.h
index c3dc1a68dd8..3cc03c64a9c 100644
--- a/arch/mips/include/asm/amon.h
+++ b/arch/mips/include/asm/amon.h
@@ -1,7 +1,12 @@
/*
- * Amon support
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * Arbitrary Monitor Support (AMON)
*/
-
-int amon_cpu_avail(int);
-void amon_cpu_start(int, unsigned long, unsigned long,
- unsigned long, unsigned long);
+int amon_cpu_avail(int cpu);
+int amon_cpu_start(int cpu, unsigned long pc, unsigned long sp,
+ unsigned long gp, unsigned long a0);
diff --git a/arch/mips/include/asm/asm-eva.h b/arch/mips/include/asm/asm-eva.h
new file mode 100644
index 00000000000..e41c56e375b
--- /dev/null
+++ b/arch/mips/include/asm/asm-eva.h
@@ -0,0 +1,135 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ *
+ */
+
+#ifndef __ASM_ASM_EVA_H
+#define __ASM_ASM_EVA_H
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_EVA
+
+#define __BUILD_EVA_INSN(insn, reg, addr) \
+ " .set push\n" \
+ " .set mips0\n" \
+ " .set eva\n" \
+ " "insn" "reg", "addr "\n" \
+ " .set pop\n"
+
+#define user_cache(op, base) __BUILD_EVA_INSN("cachee", op, base)
+#define user_ll(reg, addr) __BUILD_EVA_INSN("lle", reg, addr)
+#define user_sc(reg, addr) __BUILD_EVA_INSN("sce", reg, addr)
+#define user_lw(reg, addr) __BUILD_EVA_INSN("lwe", reg, addr)
+#define user_lwl(reg, addr) __BUILD_EVA_INSN("lwle", reg, addr)
+#define user_lwr(reg, addr) __BUILD_EVA_INSN("lwre", reg, addr)
+#define user_lh(reg, addr) __BUILD_EVA_INSN("lhe", reg, addr)
+#define user_lb(reg, addr) __BUILD_EVA_INSN("lbe", reg, addr)
+#define user_lbu(reg, addr) __BUILD_EVA_INSN("lbue", reg, addr)
+/* No 64-bit EVA instruction for loading double words */
+#define user_ld(reg, addr) user_lw(reg, addr)
+#define user_sw(reg, addr) __BUILD_EVA_INSN("swe", reg, addr)
+#define user_swl(reg, addr) __BUILD_EVA_INSN("swle", reg, addr)
+#define user_swr(reg, addr) __BUILD_EVA_INSN("swre", reg, addr)
+#define user_sh(reg, addr) __BUILD_EVA_INSN("she", reg, addr)
+#define user_sb(reg, addr) __BUILD_EVA_INSN("sbe", reg, addr)
+/* No 64-bit EVA instruction for storing double words */
+#define user_sd(reg, addr) user_sw(reg, addr)
+
+#else
+
+#define user_cache(op, base) "cache " op ", " base "\n"
+#define user_ll(reg, addr) "ll " reg ", " addr "\n"
+#define user_sc(reg, addr) "sc " reg ", " addr "\n"
+#define user_lw(reg, addr) "lw " reg ", " addr "\n"
+#define user_lwl(reg, addr) "lwl " reg ", " addr "\n"
+#define user_lwr(reg, addr) "lwr " reg ", " addr "\n"
+#define user_lh(reg, addr) "lh " reg ", " addr "\n"
+#define user_lb(reg, addr) "lb " reg ", " addr "\n"
+#define user_lbu(reg, addr) "lbu " reg ", " addr "\n"
+#define user_sw(reg, addr) "sw " reg ", " addr "\n"
+#define user_swl(reg, addr) "swl " reg ", " addr "\n"
+#define user_swr(reg, addr) "swr " reg ", " addr "\n"
+#define user_sh(reg, addr) "sh " reg ", " addr "\n"
+#define user_sb(reg, addr) "sb " reg ", " addr "\n"
+
+#ifdef CONFIG_32BIT
+/*
+ * No 'sd' or 'ld' instructions in 32-bit but the code will
+ * do the correct thing
+ */
+#define user_sd(reg, addr) user_sw(reg, addr)
+#define user_ld(reg, addr) user_lw(reg, addr)
+#else
+#define user_sd(reg, addr) "sd " reg", " addr "\n"
+#define user_ld(reg, addr) "ld " reg", " addr "\n"
+#endif /* CONFIG_32BIT */
+
+#endif /* CONFIG_EVA */
+
+#else /* __ASSEMBLY__ */
+
+#ifdef CONFIG_EVA
+
+#define __BUILD_EVA_INSN(insn, reg, addr) \
+ .set push; \
+ .set mips0; \
+ .set eva; \
+ insn reg, addr; \
+ .set pop;
+
+#define user_cache(op, base) __BUILD_EVA_INSN(cachee, op, base)
+#define user_ll(reg, addr) __BUILD_EVA_INSN(lle, reg, addr)
+#define user_sc(reg, addr) __BUILD_EVA_INSN(sce, reg, addr)
+#define user_lw(reg, addr) __BUILD_EVA_INSN(lwe, reg, addr)
+#define user_lwl(reg, addr) __BUILD_EVA_INSN(lwle, reg, addr)
+#define user_lwr(reg, addr) __BUILD_EVA_INSN(lwre, reg, addr)
+#define user_lh(reg, addr) __BUILD_EVA_INSN(lhe, reg, addr)
+#define user_lb(reg, addr) __BUILD_EVA_INSN(lbe, reg, addr)
+#define user_lbu(reg, addr) __BUILD_EVA_INSN(lbue, reg, addr)
+/* No 64-bit EVA instruction for loading double words */
+#define user_ld(reg, addr) user_lw(reg, addr)
+#define user_sw(reg, addr) __BUILD_EVA_INSN(swe, reg, addr)
+#define user_swl(reg, addr) __BUILD_EVA_INSN(swle, reg, addr)
+#define user_swr(reg, addr) __BUILD_EVA_INSN(swre, reg, addr)
+#define user_sh(reg, addr) __BUILD_EVA_INSN(she, reg, addr)
+#define user_sb(reg, addr) __BUILD_EVA_INSN(sbe, reg, addr)
+/* No 64-bit EVA instruction for loading double words */
+#define user_sd(reg, addr) user_sw(reg, addr)
+#else
+
+#define user_cache(op, base) cache op, base
+#define user_ll(reg, addr) ll reg, addr
+#define user_sc(reg, addr) sc reg, addr
+#define user_lw(reg, addr) lw reg, addr
+#define user_lwl(reg, addr) lwl reg, addr
+#define user_lwr(reg, addr) lwr reg, addr
+#define user_lh(reg, addr) lh reg, addr
+#define user_lb(reg, addr) lb reg, addr
+#define user_lbu(reg, addr) lbu reg, addr
+#define user_sw(reg, addr) sw reg, addr
+#define user_swl(reg, addr) swl reg, addr
+#define user_swr(reg, addr) swr reg, addr
+#define user_sh(reg, addr) sh reg, addr
+#define user_sb(reg, addr) sb reg, addr
+
+#ifdef CONFIG_32BIT
+/*
+ * No 'sd' or 'ld' instructions in 32-bit but the code will
+ * do the correct thing
+ */
+#define user_sd(reg, addr) user_sw(reg, addr)
+#define user_ld(reg, addr) user_lw(reg, addr)
+#else
+#define user_sd(reg, addr) sd reg, addr
+#define user_ld(reg, addr) ld reg, addr
+#endif /* CONFIG_32BIT */
+
+#endif /* CONFIG_EVA */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ASM_EVA_H */
diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h
index 879691d194a..7c26b28bf25 100644
--- a/arch/mips/include/asm/asm.h
+++ b/arch/mips/include/asm/asm.h
@@ -18,6 +18,7 @@
#define __ASM_ASM_H
#include <asm/sgidefs.h>
+#include <asm/asm-eva.h>
#ifndef CAT
#ifdef __STDC__
@@ -145,19 +146,27 @@ symbol = value
#define PREF(hint,addr) \
.set push; \
- .set mips4; \
+ .set arch=r5000; \
pref hint, addr; \
.set pop
+#define PREFE(hint, addr) \
+ .set push; \
+ .set mips0; \
+ .set eva; \
+ prefe hint, addr; \
+ .set pop
+
#define PREFX(hint,addr) \
.set push; \
- .set mips4; \
+ .set arch=r5000; \
prefx hint, addr; \
.set pop
#else /* !CONFIG_CPU_HAS_PREFETCH */
#define PREF(hint, addr)
+#define PREFE(hint, addr)
#define PREFX(hint, addr)
#endif /* !CONFIG_CPU_HAS_PREFETCH */
diff --git a/arch/mips/include/asm/asmmacro-32.h b/arch/mips/include/asm/asmmacro-32.h
index 2413afe21b3..e38c2811d4e 100644
--- a/arch/mips/include/asm/asmmacro-32.h
+++ b/arch/mips/include/asm/asmmacro-32.h
@@ -12,119 +12,77 @@
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
- .macro fpu_save_double thread status tmp1=t0
- cfc1 \tmp1, fcr31
- sdc1 $f0, THREAD_FPR0(\thread)
- sdc1 $f2, THREAD_FPR2(\thread)
- sdc1 $f4, THREAD_FPR4(\thread)
- sdc1 $f6, THREAD_FPR6(\thread)
- sdc1 $f8, THREAD_FPR8(\thread)
- sdc1 $f10, THREAD_FPR10(\thread)
- sdc1 $f12, THREAD_FPR12(\thread)
- sdc1 $f14, THREAD_FPR14(\thread)
- sdc1 $f16, THREAD_FPR16(\thread)
- sdc1 $f18, THREAD_FPR18(\thread)
- sdc1 $f20, THREAD_FPR20(\thread)
- sdc1 $f22, THREAD_FPR22(\thread)
- sdc1 $f24, THREAD_FPR24(\thread)
- sdc1 $f26, THREAD_FPR26(\thread)
- sdc1 $f28, THREAD_FPR28(\thread)
- sdc1 $f30, THREAD_FPR30(\thread)
- sw \tmp1, THREAD_FCR31(\thread)
- .endm
-
.macro fpu_save_single thread tmp=t0
cfc1 \tmp, fcr31
- swc1 $f0, THREAD_FPR0(\thread)
- swc1 $f1, THREAD_FPR1(\thread)
- swc1 $f2, THREAD_FPR2(\thread)
- swc1 $f3, THREAD_FPR3(\thread)
- swc1 $f4, THREAD_FPR4(\thread)
- swc1 $f5, THREAD_FPR5(\thread)
- swc1 $f6, THREAD_FPR6(\thread)
- swc1 $f7, THREAD_FPR7(\thread)
- swc1 $f8, THREAD_FPR8(\thread)
- swc1 $f9, THREAD_FPR9(\thread)
- swc1 $f10, THREAD_FPR10(\thread)
- swc1 $f11, THREAD_FPR11(\thread)
- swc1 $f12, THREAD_FPR12(\thread)
- swc1 $f13, THREAD_FPR13(\thread)
- swc1 $f14, THREAD_FPR14(\thread)
- swc1 $f15, THREAD_FPR15(\thread)
- swc1 $f16, THREAD_FPR16(\thread)
- swc1 $f17, THREAD_FPR17(\thread)
- swc1 $f18, THREAD_FPR18(\thread)
- swc1 $f19, THREAD_FPR19(\thread)
- swc1 $f20, THREAD_FPR20(\thread)
- swc1 $f21, THREAD_FPR21(\thread)
- swc1 $f22, THREAD_FPR22(\thread)
- swc1 $f23, THREAD_FPR23(\thread)
- swc1 $f24, THREAD_FPR24(\thread)
- swc1 $f25, THREAD_FPR25(\thread)
- swc1 $f26, THREAD_FPR26(\thread)
- swc1 $f27, THREAD_FPR27(\thread)
- swc1 $f28, THREAD_FPR28(\thread)
- swc1 $f29, THREAD_FPR29(\thread)
- swc1 $f30, THREAD_FPR30(\thread)
- swc1 $f31, THREAD_FPR31(\thread)
+ swc1 $f0, THREAD_FPR0_LS64(\thread)
+ swc1 $f1, THREAD_FPR1_LS64(\thread)
+ swc1 $f2, THREAD_FPR2_LS64(\thread)
+ swc1 $f3, THREAD_FPR3_LS64(\thread)
+ swc1 $f4, THREAD_FPR4_LS64(\thread)
+ swc1 $f5, THREAD_FPR5_LS64(\thread)
+ swc1 $f6, THREAD_FPR6_LS64(\thread)
+ swc1 $f7, THREAD_FPR7_LS64(\thread)
+ swc1 $f8, THREAD_FPR8_LS64(\thread)
+ swc1 $f9, THREAD_FPR9_LS64(\thread)
+ swc1 $f10, THREAD_FPR10_LS64(\thread)
+ swc1 $f11, THREAD_FPR11_LS64(\thread)
+ swc1 $f12, THREAD_FPR12_LS64(\thread)
+ swc1 $f13, THREAD_FPR13_LS64(\thread)
+ swc1 $f14, THREAD_FPR14_LS64(\thread)
+ swc1 $f15, THREAD_FPR15_LS64(\thread)
+ swc1 $f16, THREAD_FPR16_LS64(\thread)
+ swc1 $f17, THREAD_FPR17_LS64(\thread)
+ swc1 $f18, THREAD_FPR18_LS64(\thread)
+ swc1 $f19, THREAD_FPR19_LS64(\thread)
+ swc1 $f20, THREAD_FPR20_LS64(\thread)
+ swc1 $f21, THREAD_FPR21_LS64(\thread)
+ swc1 $f22, THREAD_FPR22_LS64(\thread)
+ swc1 $f23, THREAD_FPR23_LS64(\thread)
+ swc1 $f24, THREAD_FPR24_LS64(\thread)
+ swc1 $f25, THREAD_FPR25_LS64(\thread)
+ swc1 $f26, THREAD_FPR26_LS64(\thread)
+ swc1 $f27, THREAD_FPR27_LS64(\thread)
+ swc1 $f28, THREAD_FPR28_LS64(\thread)
+ swc1 $f29, THREAD_FPR29_LS64(\thread)
+ swc1 $f30, THREAD_FPR30_LS64(\thread)
+ swc1 $f31, THREAD_FPR31_LS64(\thread)
sw \tmp, THREAD_FCR31(\thread)
.endm
- .macro fpu_restore_double thread status tmp=t0
- lw \tmp, THREAD_FCR31(\thread)
- ldc1 $f0, THREAD_FPR0(\thread)
- ldc1 $f2, THREAD_FPR2(\thread)
- ldc1 $f4, THREAD_FPR4(\thread)
- ldc1 $f6, THREAD_FPR6(\thread)
- ldc1 $f8, THREAD_FPR8(\thread)
- ldc1 $f10, THREAD_FPR10(\thread)
- ldc1 $f12, THREAD_FPR12(\thread)
- ldc1 $f14, THREAD_FPR14(\thread)
- ldc1 $f16, THREAD_FPR16(\thread)
- ldc1 $f18, THREAD_FPR18(\thread)
- ldc1 $f20, THREAD_FPR20(\thread)
- ldc1 $f22, THREAD_FPR22(\thread)
- ldc1 $f24, THREAD_FPR24(\thread)
- ldc1 $f26, THREAD_FPR26(\thread)
- ldc1 $f28, THREAD_FPR28(\thread)
- ldc1 $f30, THREAD_FPR30(\thread)
- ctc1 \tmp, fcr31
- .endm
-
.macro fpu_restore_single thread tmp=t0
lw \tmp, THREAD_FCR31(\thread)
- lwc1 $f0, THREAD_FPR0(\thread)
- lwc1 $f1, THREAD_FPR1(\thread)
- lwc1 $f2, THREAD_FPR2(\thread)
- lwc1 $f3, THREAD_FPR3(\thread)
- lwc1 $f4, THREAD_FPR4(\thread)
- lwc1 $f5, THREAD_FPR5(\thread)
- lwc1 $f6, THREAD_FPR6(\thread)
- lwc1 $f7, THREAD_FPR7(\thread)
- lwc1 $f8, THREAD_FPR8(\thread)
- lwc1 $f9, THREAD_FPR9(\thread)
- lwc1 $f10, THREAD_FPR10(\thread)
- lwc1 $f11, THREAD_FPR11(\thread)
- lwc1 $f12, THREAD_FPR12(\thread)
- lwc1 $f13, THREAD_FPR13(\thread)
- lwc1 $f14, THREAD_FPR14(\thread)
- lwc1 $f15, THREAD_FPR15(\thread)
- lwc1 $f16, THREAD_FPR16(\thread)
- lwc1 $f17, THREAD_FPR17(\thread)
- lwc1 $f18, THREAD_FPR18(\thread)
- lwc1 $f19, THREAD_FPR19(\thread)
- lwc1 $f20, THREAD_FPR20(\thread)
- lwc1 $f21, THREAD_FPR21(\thread)
- lwc1 $f22, THREAD_FPR22(\thread)
- lwc1 $f23, THREAD_FPR23(\thread)
- lwc1 $f24, THREAD_FPR24(\thread)
- lwc1 $f25, THREAD_FPR25(\thread)
- lwc1 $f26, THREAD_FPR26(\thread)
- lwc1 $f27, THREAD_FPR27(\thread)
- lwc1 $f28, THREAD_FPR28(\thread)
- lwc1 $f29, THREAD_FPR29(\thread)
- lwc1 $f30, THREAD_FPR30(\thread)
- lwc1 $f31, THREAD_FPR31(\thread)
+ lwc1 $f0, THREAD_FPR0_LS64(\thread)
+ lwc1 $f1, THREAD_FPR1_LS64(\thread)
+ lwc1 $f2, THREAD_FPR2_LS64(\thread)
+ lwc1 $f3, THREAD_FPR3_LS64(\thread)
+ lwc1 $f4, THREAD_FPR4_LS64(\thread)
+ lwc1 $f5, THREAD_FPR5_LS64(\thread)
+ lwc1 $f6, THREAD_FPR6_LS64(\thread)
+ lwc1 $f7, THREAD_FPR7_LS64(\thread)
+ lwc1 $f8, THREAD_FPR8_LS64(\thread)
+ lwc1 $f9, THREAD_FPR9_LS64(\thread)
+ lwc1 $f10, THREAD_FPR10_LS64(\thread)
+ lwc1 $f11, THREAD_FPR11_LS64(\thread)
+ lwc1 $f12, THREAD_FPR12_LS64(\thread)
+ lwc1 $f13, THREAD_FPR13_LS64(\thread)
+ lwc1 $f14, THREAD_FPR14_LS64(\thread)
+ lwc1 $f15, THREAD_FPR15_LS64(\thread)
+ lwc1 $f16, THREAD_FPR16_LS64(\thread)
+ lwc1 $f17, THREAD_FPR17_LS64(\thread)
+ lwc1 $f18, THREAD_FPR18_LS64(\thread)
+ lwc1 $f19, THREAD_FPR19_LS64(\thread)
+ lwc1 $f20, THREAD_FPR20_LS64(\thread)
+ lwc1 $f21, THREAD_FPR21_LS64(\thread)
+ lwc1 $f22, THREAD_FPR22_LS64(\thread)
+ lwc1 $f23, THREAD_FPR23_LS64(\thread)
+ lwc1 $f24, THREAD_FPR24_LS64(\thread)
+ lwc1 $f25, THREAD_FPR25_LS64(\thread)
+ lwc1 $f26, THREAD_FPR26_LS64(\thread)
+ lwc1 $f27, THREAD_FPR27_LS64(\thread)
+ lwc1 $f28, THREAD_FPR28_LS64(\thread)
+ lwc1 $f29, THREAD_FPR29_LS64(\thread)
+ lwc1 $f30, THREAD_FPR30_LS64(\thread)
+ lwc1 $f31, THREAD_FPR31_LS64(\thread)
ctc1 \tmp, fcr31
.endm
diff --git a/arch/mips/include/asm/asmmacro-64.h b/arch/mips/include/asm/asmmacro-64.h
index 08a527dfe4a..38ea609465b 100644
--- a/arch/mips/include/asm/asmmacro-64.h
+++ b/arch/mips/include/asm/asmmacro-64.h
@@ -13,102 +13,6 @@
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
- .macro fpu_save_16even thread tmp=t0
- cfc1 \tmp, fcr31
- sdc1 $f0, THREAD_FPR0(\thread)
- sdc1 $f2, THREAD_FPR2(\thread)
- sdc1 $f4, THREAD_FPR4(\thread)
- sdc1 $f6, THREAD_FPR6(\thread)
- sdc1 $f8, THREAD_FPR8(\thread)
- sdc1 $f10, THREAD_FPR10(\thread)
- sdc1 $f12, THREAD_FPR12(\thread)
- sdc1 $f14, THREAD_FPR14(\thread)
- sdc1 $f16, THREAD_FPR16(\thread)
- sdc1 $f18, THREAD_FPR18(\thread)
- sdc1 $f20, THREAD_FPR20(\thread)
- sdc1 $f22, THREAD_FPR22(\thread)
- sdc1 $f24, THREAD_FPR24(\thread)
- sdc1 $f26, THREAD_FPR26(\thread)
- sdc1 $f28, THREAD_FPR28(\thread)
- sdc1 $f30, THREAD_FPR30(\thread)
- sw \tmp, THREAD_FCR31(\thread)
- .endm
-
- .macro fpu_save_16odd thread
- sdc1 $f1, THREAD_FPR1(\thread)
- sdc1 $f3, THREAD_FPR3(\thread)
- sdc1 $f5, THREAD_FPR5(\thread)
- sdc1 $f7, THREAD_FPR7(\thread)
- sdc1 $f9, THREAD_FPR9(\thread)
- sdc1 $f11, THREAD_FPR11(\thread)
- sdc1 $f13, THREAD_FPR13(\thread)
- sdc1 $f15, THREAD_FPR15(\thread)
- sdc1 $f17, THREAD_FPR17(\thread)
- sdc1 $f19, THREAD_FPR19(\thread)
- sdc1 $f21, THREAD_FPR21(\thread)
- sdc1 $f23, THREAD_FPR23(\thread)
- sdc1 $f25, THREAD_FPR25(\thread)
- sdc1 $f27, THREAD_FPR27(\thread)
- sdc1 $f29, THREAD_FPR29(\thread)
- sdc1 $f31, THREAD_FPR31(\thread)
- .endm
-
- .macro fpu_save_double thread status tmp
- sll \tmp, \status, 5
- bgez \tmp, 2f
- fpu_save_16odd \thread
-2:
- fpu_save_16even \thread \tmp
- .endm
-
- .macro fpu_restore_16even thread tmp=t0
- lw \tmp, THREAD_FCR31(\thread)
- ldc1 $f0, THREAD_FPR0(\thread)
- ldc1 $f2, THREAD_FPR2(\thread)
- ldc1 $f4, THREAD_FPR4(\thread)
- ldc1 $f6, THREAD_FPR6(\thread)
- ldc1 $f8, THREAD_FPR8(\thread)
- ldc1 $f10, THREAD_FPR10(\thread)
- ldc1 $f12, THREAD_FPR12(\thread)
- ldc1 $f14, THREAD_FPR14(\thread)
- ldc1 $f16, THREAD_FPR16(\thread)
- ldc1 $f18, THREAD_FPR18(\thread)
- ldc1 $f20, THREAD_FPR20(\thread)
- ldc1 $f22, THREAD_FPR22(\thread)
- ldc1 $f24, THREAD_FPR24(\thread)
- ldc1 $f26, THREAD_FPR26(\thread)
- ldc1 $f28, THREAD_FPR28(\thread)
- ldc1 $f30, THREAD_FPR30(\thread)
- ctc1 \tmp, fcr31
- .endm
-
- .macro fpu_restore_16odd thread
- ldc1 $f1, THREAD_FPR1(\thread)
- ldc1 $f3, THREAD_FPR3(\thread)
- ldc1 $f5, THREAD_FPR5(\thread)
- ldc1 $f7, THREAD_FPR7(\thread)
- ldc1 $f9, THREAD_FPR9(\thread)
- ldc1 $f11, THREAD_FPR11(\thread)
- ldc1 $f13, THREAD_FPR13(\thread)
- ldc1 $f15, THREAD_FPR15(\thread)
- ldc1 $f17, THREAD_FPR17(\thread)
- ldc1 $f19, THREAD_FPR19(\thread)
- ldc1 $f21, THREAD_FPR21(\thread)
- ldc1 $f23, THREAD_FPR23(\thread)
- ldc1 $f25, THREAD_FPR25(\thread)
- ldc1 $f27, THREAD_FPR27(\thread)
- ldc1 $f29, THREAD_FPR29(\thread)
- ldc1 $f31, THREAD_FPR31(\thread)
- .endm
-
- .macro fpu_restore_double thread status tmp
- sll \tmp, \status, 5
- bgez \tmp, 1f # 16 register mode?
-
- fpu_restore_16odd \thread
-1: fpu_restore_16even \thread \tmp
- .endm
-
.macro cpu_save_nonscratch thread
LONG_S s0, THREAD_REG16(\thread)
LONG_S s1, THREAD_REG17(\thread)
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 6c8342ae74d..935543f1453 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -9,6 +9,7 @@
#define _ASM_ASMMACRO_H
#include <asm/hazards.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_32BIT
#include <asm/asmmacro-32.h>
@@ -16,26 +17,8 @@
#ifdef CONFIG_64BIT
#include <asm/asmmacro-64.h>
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/mipsmtregs.h>
-#endif
-
-#ifdef CONFIG_MIPS_MT_SMTC
- .macro local_irq_enable reg=t0
- mfc0 \reg, CP0_TCSTATUS
- ori \reg, \reg, TCSTATUS_IXMT
- xori \reg, \reg, TCSTATUS_IXMT
- mtc0 \reg, CP0_TCSTATUS
- _ehb
- .endm
- .macro local_irq_disable reg=t0
- mfc0 \reg, CP0_TCSTATUS
- ori \reg, \reg, TCSTATUS_IXMT
- mtc0 \reg, CP0_TCSTATUS
- _ehb
- .endm
-#elif defined(CONFIG_CPU_MIPSR2)
+#ifdef CONFIG_CPU_MIPSR2
.macro local_irq_enable reg=t0
ei
irq_enable_hazard
@@ -54,13 +37,141 @@
.endm
.macro local_irq_disable reg=t0
+#ifdef CONFIG_PREEMPT
+ lw \reg, TI_PRE_COUNT($28)
+ addi \reg, \reg, 1
+ sw \reg, TI_PRE_COUNT($28)
+#endif
mfc0 \reg, CP0_STATUS
ori \reg, \reg, 1
xori \reg, \reg, 1
mtc0 \reg, CP0_STATUS
irq_disable_hazard
+#ifdef CONFIG_PREEMPT
+ lw \reg, TI_PRE_COUNT($28)
+ addi \reg, \reg, -1
+ sw \reg, TI_PRE_COUNT($28)
+#endif
+ .endm
+#endif /* CONFIG_CPU_MIPSR2 */
+
+ .macro fpu_save_16even thread tmp=t0
+ cfc1 \tmp, fcr31
+ sdc1 $f0, THREAD_FPR0_LS64(\thread)
+ sdc1 $f2, THREAD_FPR2_LS64(\thread)
+ sdc1 $f4, THREAD_FPR4_LS64(\thread)
+ sdc1 $f6, THREAD_FPR6_LS64(\thread)
+ sdc1 $f8, THREAD_FPR8_LS64(\thread)
+ sdc1 $f10, THREAD_FPR10_LS64(\thread)
+ sdc1 $f12, THREAD_FPR12_LS64(\thread)
+ sdc1 $f14, THREAD_FPR14_LS64(\thread)
+ sdc1 $f16, THREAD_FPR16_LS64(\thread)
+ sdc1 $f18, THREAD_FPR18_LS64(\thread)
+ sdc1 $f20, THREAD_FPR20_LS64(\thread)
+ sdc1 $f22, THREAD_FPR22_LS64(\thread)
+ sdc1 $f24, THREAD_FPR24_LS64(\thread)
+ sdc1 $f26, THREAD_FPR26_LS64(\thread)
+ sdc1 $f28, THREAD_FPR28_LS64(\thread)
+ sdc1 $f30, THREAD_FPR30_LS64(\thread)
+ sw \tmp, THREAD_FCR31(\thread)
+ .endm
+
+ .macro fpu_save_16odd thread
+ .set push
+ .set mips64r2
+ sdc1 $f1, THREAD_FPR1_LS64(\thread)
+ sdc1 $f3, THREAD_FPR3_LS64(\thread)
+ sdc1 $f5, THREAD_FPR5_LS64(\thread)
+ sdc1 $f7, THREAD_FPR7_LS64(\thread)
+ sdc1 $f9, THREAD_FPR9_LS64(\thread)
+ sdc1 $f11, THREAD_FPR11_LS64(\thread)
+ sdc1 $f13, THREAD_FPR13_LS64(\thread)
+ sdc1 $f15, THREAD_FPR15_LS64(\thread)
+ sdc1 $f17, THREAD_FPR17_LS64(\thread)
+ sdc1 $f19, THREAD_FPR19_LS64(\thread)
+ sdc1 $f21, THREAD_FPR21_LS64(\thread)
+ sdc1 $f23, THREAD_FPR23_LS64(\thread)
+ sdc1 $f25, THREAD_FPR25_LS64(\thread)
+ sdc1 $f27, THREAD_FPR27_LS64(\thread)
+ sdc1 $f29, THREAD_FPR29_LS64(\thread)
+ sdc1 $f31, THREAD_FPR31_LS64(\thread)
+ .set pop
+ .endm
+
+ .macro fpu_save_double thread status tmp
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+ sll \tmp, \status, 5
+ bgez \tmp, 10f
+ fpu_save_16odd \thread
+10:
+#endif
+ fpu_save_16even \thread \tmp
+ .endm
+
+ .macro fpu_restore_16even thread tmp=t0
+ lw \tmp, THREAD_FCR31(\thread)
+ ldc1 $f0, THREAD_FPR0_LS64(\thread)
+ ldc1 $f2, THREAD_FPR2_LS64(\thread)
+ ldc1 $f4, THREAD_FPR4_LS64(\thread)
+ ldc1 $f6, THREAD_FPR6_LS64(\thread)
+ ldc1 $f8, THREAD_FPR8_LS64(\thread)
+ ldc1 $f10, THREAD_FPR10_LS64(\thread)
+ ldc1 $f12, THREAD_FPR12_LS64(\thread)
+ ldc1 $f14, THREAD_FPR14_LS64(\thread)
+ ldc1 $f16, THREAD_FPR16_LS64(\thread)
+ ldc1 $f18, THREAD_FPR18_LS64(\thread)
+ ldc1 $f20, THREAD_FPR20_LS64(\thread)
+ ldc1 $f22, THREAD_FPR22_LS64(\thread)
+ ldc1 $f24, THREAD_FPR24_LS64(\thread)
+ ldc1 $f26, THREAD_FPR26_LS64(\thread)
+ ldc1 $f28, THREAD_FPR28_LS64(\thread)
+ ldc1 $f30, THREAD_FPR30_LS64(\thread)
+ ctc1 \tmp, fcr31
+ .endm
+
+ .macro fpu_restore_16odd thread
+ .set push
+ .set mips64r2
+ ldc1 $f1, THREAD_FPR1_LS64(\thread)
+ ldc1 $f3, THREAD_FPR3_LS64(\thread)
+ ldc1 $f5, THREAD_FPR5_LS64(\thread)
+ ldc1 $f7, THREAD_FPR7_LS64(\thread)
+ ldc1 $f9, THREAD_FPR9_LS64(\thread)
+ ldc1 $f11, THREAD_FPR11_LS64(\thread)
+ ldc1 $f13, THREAD_FPR13_LS64(\thread)
+ ldc1 $f15, THREAD_FPR15_LS64(\thread)
+ ldc1 $f17, THREAD_FPR17_LS64(\thread)
+ ldc1 $f19, THREAD_FPR19_LS64(\thread)
+ ldc1 $f21, THREAD_FPR21_LS64(\thread)
+ ldc1 $f23, THREAD_FPR23_LS64(\thread)
+ ldc1 $f25, THREAD_FPR25_LS64(\thread)
+ ldc1 $f27, THREAD_FPR27_LS64(\thread)
+ ldc1 $f29, THREAD_FPR29_LS64(\thread)
+ ldc1 $f31, THREAD_FPR31_LS64(\thread)
+ .set pop
+ .endm
+
+ .macro fpu_restore_double thread status tmp
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+ sll \tmp, \status, 5
+ bgez \tmp, 10f # 16 register mode?
+
+ fpu_restore_16odd \thread
+10:
+#endif
+ fpu_restore_16even \thread \tmp
+ .endm
+
+#ifdef CONFIG_CPU_MIPSR2
+ .macro _EXT rd, rs, p, s
+ ext \rd, \rs, \p, \s
+ .endm
+#else /* !CONFIG_CPU_MIPSR2 */
+ .macro _EXT rd, rs, p, s
+ srl \rd, \rs, \p
+ andi \rd, \rd, (1 << \s) - 1
.endm
-#endif /* CONFIG_MIPS_MT_SMTC */
+#endif /* !CONFIG_CPU_MIPSR2 */
/*
* Temporary until all gas have MT ASE support
@@ -89,4 +200,219 @@
.word 0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel)
.endm
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+ .macro ld_d wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ ld.d $w\wd, \off(\base)
+ .set pop
+ .endm
+
+ .macro st_d wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ st.d $w\wd, \off(\base)
+ .set pop
+ .endm
+
+ .macro copy_u_w rd, ws, n
+ .set push
+ .set mips32r2
+ .set msa
+ copy_u.w \rd, $w\ws[\n]
+ .set pop
+ .endm
+
+ .macro copy_u_d rd, ws, n
+ .set push
+ .set mips64r2
+ .set msa
+ copy_u.d \rd, $w\ws[\n]
+ .set pop
+ .endm
+
+ .macro insert_w wd, n, rs
+ .set push
+ .set mips32r2
+ .set msa
+ insert.w $w\wd[\n], \rs
+ .set pop
+ .endm
+
+ .macro insert_d wd, n, rs
+ .set push
+ .set mips64r2
+ .set msa
+ insert.d $w\wd[\n], \rs
+ .set pop
+ .endm
+#else
+
+#ifdef CONFIG_CPU_MICROMIPS
+#define CFC_MSA_INSN 0x587e0056
+#define CTC_MSA_INSN 0x583e0816
+#define LDD_MSA_INSN 0x58000837
+#define STD_MSA_INSN 0x5800083f
+#define COPY_UW_MSA_INSN 0x58f00056
+#define COPY_UD_MSA_INSN 0x58f80056
+#define INSERT_W_MSA_INSN 0x59300816
+#define INSERT_D_MSA_INSN 0x59380816
+#else
+#define CFC_MSA_INSN 0x787e0059
+#define CTC_MSA_INSN 0x783e0819
+#define LDD_MSA_INSN 0x78000823
+#define STD_MSA_INSN 0x78000827
+#define COPY_UW_MSA_INSN 0x78f00059
+#define COPY_UD_MSA_INSN 0x78f80059
+#define INSERT_W_MSA_INSN 0x79300819
+#define INSERT_D_MSA_INSN 0x79380819
+#endif
+
+ /*
+ * Temporary until all toolchains in use include MSA support.
+ */
+ .macro cfcmsa rd, cs
+ .set push
+ .set noat
+ .insn
+ .word CFC_MSA_INSN | (\cs << 11)
+ move \rd, $1
+ .set pop
+ .endm
+
+ .macro ctcmsa cd, rs
+ .set push
+ .set noat
+ move $1, \rs
+ .word CTC_MSA_INSN | (\cd << 6)
+ .set pop
+ .endm
+
+ .macro ld_d wd, off, base
+ .set push
+ .set noat
+ add $1, \base, \off
+ .word LDD_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
+ .macro st_d wd, off, base
+ .set push
+ .set noat
+ add $1, \base, \off
+ .word STD_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
+ .macro copy_u_w rd, ws, n
+ .set push
+ .set noat
+ .insn
+ .word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
+ /* move triggers an assembler bug... */
+ or \rd, $1, zero
+ .set pop
+ .endm
+
+ .macro copy_u_d rd, ws, n
+ .set push
+ .set noat
+ .insn
+ .word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
+ /* move triggers an assembler bug... */
+ or \rd, $1, zero
+ .set pop
+ .endm
+
+ .macro insert_w wd, n, rs
+ .set push
+ .set noat
+ /* move triggers an assembler bug... */
+ or $1, \rs, zero
+ .word INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
+ .set pop
+ .endm
+
+ .macro insert_d wd, n, rs
+ .set push
+ .set noat
+ /* move triggers an assembler bug... */
+ or $1, \rs, zero
+ .word INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
+ .set pop
+ .endm
+#endif
+
+ .macro msa_save_all thread
+ st_d 0, THREAD_FPR0, \thread
+ st_d 1, THREAD_FPR1, \thread
+ st_d 2, THREAD_FPR2, \thread
+ st_d 3, THREAD_FPR3, \thread
+ st_d 4, THREAD_FPR4, \thread
+ st_d 5, THREAD_FPR5, \thread
+ st_d 6, THREAD_FPR6, \thread
+ st_d 7, THREAD_FPR7, \thread
+ st_d 8, THREAD_FPR8, \thread
+ st_d 9, THREAD_FPR9, \thread
+ st_d 10, THREAD_FPR10, \thread
+ st_d 11, THREAD_FPR11, \thread
+ st_d 12, THREAD_FPR12, \thread
+ st_d 13, THREAD_FPR13, \thread
+ st_d 14, THREAD_FPR14, \thread
+ st_d 15, THREAD_FPR15, \thread
+ st_d 16, THREAD_FPR16, \thread
+ st_d 17, THREAD_FPR17, \thread
+ st_d 18, THREAD_FPR18, \thread
+ st_d 19, THREAD_FPR19, \thread
+ st_d 20, THREAD_FPR20, \thread
+ st_d 21, THREAD_FPR21, \thread
+ st_d 22, THREAD_FPR22, \thread
+ st_d 23, THREAD_FPR23, \thread
+ st_d 24, THREAD_FPR24, \thread
+ st_d 25, THREAD_FPR25, \thread
+ st_d 26, THREAD_FPR26, \thread
+ st_d 27, THREAD_FPR27, \thread
+ st_d 28, THREAD_FPR28, \thread
+ st_d 29, THREAD_FPR29, \thread
+ st_d 30, THREAD_FPR30, \thread
+ st_d 31, THREAD_FPR31, \thread
+ .endm
+
+ .macro msa_restore_all thread
+ ld_d 0, THREAD_FPR0, \thread
+ ld_d 1, THREAD_FPR1, \thread
+ ld_d 2, THREAD_FPR2, \thread
+ ld_d 3, THREAD_FPR3, \thread
+ ld_d 4, THREAD_FPR4, \thread
+ ld_d 5, THREAD_FPR5, \thread
+ ld_d 6, THREAD_FPR6, \thread
+ ld_d 7, THREAD_FPR7, \thread
+ ld_d 8, THREAD_FPR8, \thread
+ ld_d 9, THREAD_FPR9, \thread
+ ld_d 10, THREAD_FPR10, \thread
+ ld_d 11, THREAD_FPR11, \thread
+ ld_d 12, THREAD_FPR12, \thread
+ ld_d 13, THREAD_FPR13, \thread
+ ld_d 14, THREAD_FPR14, \thread
+ ld_d 15, THREAD_FPR15, \thread
+ ld_d 16, THREAD_FPR16, \thread
+ ld_d 17, THREAD_FPR17, \thread
+ ld_d 18, THREAD_FPR18, \thread
+ ld_d 19, THREAD_FPR19, \thread
+ ld_d 20, THREAD_FPR20, \thread
+ ld_d 21, THREAD_FPR21, \thread
+ ld_d 22, THREAD_FPR22, \thread
+ ld_d 23, THREAD_FPR23, \thread
+ ld_d 24, THREAD_FPR24, \thread
+ ld_d 25, THREAD_FPR25, \thread
+ ld_d 26, THREAD_FPR26, \thread
+ ld_d 27, THREAD_FPR27, \thread
+ ld_d 28, THREAD_FPR28, \thread
+ ld_d 29, THREAD_FPR29, \thread
+ ld_d 30, THREAD_FPR30, \thread
+ ld_d 31, THREAD_FPR31, \thread
+ .endm
+
#endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 08b607969a1..37b2befe651 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -1,5 +1,5 @@
/*
- * Atomic operations that C can't guarantee us. Useful for
+ * Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
*
* But use these as seldom as possible since they are much more slower
@@ -53,7 +53,7 @@ static __inline__ void atomic_add(int i, atomic_t * v)
int temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %0, %1 # atomic_add \n"
" addu %0, %2 \n"
" sc %0, %1 \n"
@@ -66,7 +66,7 @@ static __inline__ void atomic_add(int i, atomic_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" ll %0, %1 # atomic_add \n"
" addu %0, %2 \n"
" sc %0, %1 \n"
@@ -96,7 +96,7 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
int temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %0, %1 # atomic_sub \n"
" subu %0, %2 \n"
" sc %0, %1 \n"
@@ -109,7 +109,7 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" ll %0, %1 # atomic_sub \n"
" subu %0, %2 \n"
" sc %0, %1 \n"
@@ -139,7 +139,7 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
int temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %1, %2 # atomic_add_return \n"
" addu %0, %1, %3 \n"
" sc %0, %2 \n"
@@ -153,7 +153,7 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" ll %1, %2 # atomic_add_return \n"
" addu %0, %1, %3 \n"
" sc %0, %2 \n"
@@ -188,7 +188,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
int temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %1, %2 # atomic_sub_return \n"
" subu %0, %1, %3 \n"
" sc %0, %2 \n"
@@ -205,7 +205,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" ll %1, %2 # atomic_sub_return \n"
" subu %0, %1, %3 \n"
" sc %0, %2 \n"
@@ -248,7 +248,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
int temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %1, %2 # atomic_sub_if_positive\n"
" subu %0, %1, %3 \n"
" bltz %0, 1f \n"
@@ -266,7 +266,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
int temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %1, %2 # atomic_sub_if_positive\n"
" subu %0, %1, %3 \n"
" bltz %0, 1f \n"
@@ -420,7 +420,7 @@ static __inline__ void atomic64_add(long i, atomic64_t * v)
long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: lld %0, %1 # atomic64_add \n"
" daddu %0, %2 \n"
" scd %0, %1 \n"
@@ -433,7 +433,7 @@ static __inline__ void atomic64_add(long i, atomic64_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" lld %0, %1 # atomic64_add \n"
" daddu %0, %2 \n"
" scd %0, %1 \n"
@@ -463,7 +463,7 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: lld %0, %1 # atomic64_sub \n"
" dsubu %0, %2 \n"
" scd %0, %1 \n"
@@ -476,7 +476,7 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" lld %0, %1 # atomic64_sub \n"
" dsubu %0, %2 \n"
" scd %0, %1 \n"
@@ -506,7 +506,7 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: lld %1, %2 # atomic64_add_return \n"
" daddu %0, %1, %3 \n"
" scd %0, %2 \n"
@@ -520,7 +520,7 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" lld %1, %2 # atomic64_add_return \n"
" daddu %0, %1, %3 \n"
" scd %0, %2 \n"
@@ -556,7 +556,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: lld %1, %2 # atomic64_sub_return \n"
" dsubu %0, %1, %3 \n"
" scd %0, %2 \n"
@@ -571,7 +571,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" lld %1, %2 # atomic64_sub_return \n"
" dsubu %0, %1, %3 \n"
" scd %0, %2 \n"
@@ -615,7 +615,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: lld %1, %2 # atomic64_sub_if_positive\n"
" dsubu %0, %1, %3 \n"
" bltz %0, 1f \n"
@@ -633,7 +633,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: lld %1, %2 # atomic64_sub_if_positive\n"
" dsubu %0, %1, %3 \n"
" bltz %0, 1f \n"
@@ -761,13 +761,4 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
#endif /* CONFIG_64BIT */
-/*
- * atomic*_return operations are serializing but not the non-*_return
- * versions.
- */
-#define smp_mb__before_atomic_dec() smp_mb__before_llsc()
-#define smp_mb__after_atomic_dec() smp_llsc_mb()
-#define smp_mb__before_atomic_inc() smp_mb__before_llsc()
-#define smp_mb__after_atomic_inc() smp_llsc_mb()
-
#endif /* _ASM_ATOMIC_H */
diff --git a/arch/mips/include/asm/barrier.h b/arch/mips/include/asm/barrier.h
index 314ab553201..d0101dd0575 100644
--- a/arch/mips/include/asm/barrier.h
+++ b/arch/mips/include/asm/barrier.h
@@ -18,7 +18,7 @@
* over this barrier. All reads preceding this primitive are guaranteed
* to access memory (but not necessarily other CPUs' caches) before any
* reads following this primitive that depend on the data return by
- * any of the preceding reads. This primitive is much lighter weight than
+ * any of the preceding reads. This primitive is much lighter weight than
* rmb() on most CPUs, and is never heavier weight than is
* rmb().
*
@@ -43,7 +43,7 @@
* </programlisting>
*
* because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends(). However,
+ * two reads are separated by a read_barrier_depends(). However,
* the following code, with the same initial values for "a" and "b":
*
* <programlisting>
@@ -57,7 +57,7 @@
* </programlisting>
*
* does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b". Therefore, on some CPUs, such
+ * the read of "a" and the read of "b". Therefore, on some CPUs, such
* as Alpha, "y" could be set to 3 and "x" to 0. Use rmb()
* in cases like this where there are no data dependencies.
*/
@@ -180,4 +180,22 @@
#define nudge_writes() mb()
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
+#define smp_mb__before_atomic() smp_mb__before_llsc()
+#define smp_mb__after_atomic() smp_llsc_mb()
+
#endif /* __ASM_BARRIER_H */
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 71305a8b3d7..7c8816f7b7c 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -38,13 +38,6 @@
#endif
/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit() smp_mb__before_llsc()
-#define smp_mb__after_clear_bit() smp_llsc_mb()
-
-
-/*
* These are the "slower" versions of the functions and are in bitops.c.
* These functions call raw_local_irq_{save,restore}().
*/
@@ -79,7 +72,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
if (kernel_uses_llsc && R10000_LLSC_WAR) {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: " __LL "%0, %1 # set_bit \n"
" or %0, %2 \n"
" " __SC "%0, %1 \n"
@@ -101,7 +94,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
} else if (kernel_uses_llsc) {
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" " __LL "%0, %1 # set_bit \n"
" or %0, %2 \n"
" " __SC "%0, %1 \n"
@@ -120,7 +113,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
*
* clear_bit() is atomic and may not be reordered. However, it does
* not contain a memory barrier, so if it is used for locking purposes,
- * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
* in order to ensure changes are visible on other processors.
*/
static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
@@ -131,7 +124,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
if (kernel_uses_llsc && R10000_LLSC_WAR) {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: " __LL "%0, %1 # clear_bit \n"
" and %0, %2 \n"
" " __SC "%0, %1 \n"
@@ -153,7 +146,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
} else if (kernel_uses_llsc) {
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" " __LL "%0, %1 # clear_bit \n"
" and %0, %2 \n"
" " __SC "%0, %1 \n"
@@ -175,7 +168,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
*/
static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
{
- smp_mb__before_clear_bit();
+ smp_mb__before_atomic();
clear_bit(nr, addr);
}
@@ -197,7 +190,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: " __LL "%0, %1 # change_bit \n"
" xor %0, %2 \n"
" " __SC "%0, %1 \n"
@@ -211,7 +204,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" " __LL "%0, %1 # change_bit \n"
" xor %0, %2 \n"
" " __SC "%0, %1 \n"
@@ -244,7 +237,7 @@ static inline int test_and_set_bit(unsigned long nr,
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: " __LL "%0, %1 # test_and_set_bit \n"
" or %2, %0, %3 \n"
" " __SC "%2, %1 \n"
@@ -260,7 +253,7 @@ static inline int test_and_set_bit(unsigned long nr,
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" " __LL "%0, %1 # test_and_set_bit \n"
" or %2, %0, %3 \n"
" " __SC "%2, %1 \n"
@@ -298,7 +291,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: " __LL "%0, %1 # test_and_set_bit \n"
" or %2, %0, %3 \n"
" " __SC "%2, %1 \n"
@@ -314,7 +307,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" " __LL "%0, %1 # test_and_set_bit \n"
" or %2, %0, %3 \n"
" " __SC "%2, %1 \n"
@@ -353,7 +346,7 @@ static inline int test_and_clear_bit(unsigned long nr,
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: " __LL "%0, %1 # test_and_clear_bit \n"
" or %2, %0, %3 \n"
" xor %2, %3 \n"
@@ -386,7 +379,7 @@ static inline int test_and_clear_bit(unsigned long nr,
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" " __LL "%0, %1 # test_and_clear_bit \n"
" or %2, %0, %3 \n"
" xor %2, %3 \n"
@@ -427,7 +420,7 @@ static inline int test_and_change_bit(unsigned long nr,
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: " __LL "%0, %1 # test_and_change_bit \n"
" xor %2, %0, %3 \n"
" " __SC "%2, %1 \n"
@@ -443,7 +436,7 @@ static inline int test_and_change_bit(unsigned long nr,
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" " __LL "%0, %1 # test_and_change_bit \n"
" xor %2, %0, %3 \n"
" " __SC "\t%2, %1 \n"
diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h
index 27bd060d716..cbaccebf506 100644
--- a/arch/mips/include/asm/bmips.h
+++ b/arch/mips/include/asm/bmips.h
@@ -46,8 +46,35 @@
#include <linux/cpumask.h>
#include <asm/r4kcache.h>
+#include <asm/smp-ops.h>
+
+extern struct plat_smp_ops bmips43xx_smp_ops;
+extern struct plat_smp_ops bmips5000_smp_ops;
+
+static inline int register_bmips_smp_ops(void)
+{
+#if IS_ENABLED(CONFIG_CPU_BMIPS) && IS_ENABLED(CONFIG_SMP)
+ switch (current_cpu_type()) {
+ case CPU_BMIPS32:
+ case CPU_BMIPS3300:
+ return register_up_smp_ops();
+ case CPU_BMIPS4350:
+ case CPU_BMIPS4380:
+ register_smp_ops(&bmips43xx_smp_ops);
+ break;
+ case CPU_BMIPS5000:
+ register_smp_ops(&bmips5000_smp_ops);
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ return 0;
+#else
+ return -ENODEV;
+#endif
+}
-extern struct plat_smp_ops bmips_smp_ops;
extern char bmips_reset_nmi_vec;
extern char bmips_reset_nmi_vec_end;
extern char bmips_smp_movevec;
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 4d2cdea5aa3..1f7ca8b0040 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -61,15 +61,21 @@
/*
* Valid machtype for Loongson family
*/
-#define MACH_LOONGSON_UNKNOWN 0
-#define MACH_LEMOTE_FL2E 1
-#define MACH_LEMOTE_FL2F 2
-#define MACH_LEMOTE_ML2F7 3
-#define MACH_LEMOTE_YL2F89 4
-#define MACH_DEXXON_GDIUM2F10 5
-#define MACH_LEMOTE_NAS 6
-#define MACH_LEMOTE_LL2F 7
-#define MACH_LOONGSON_END 8
+enum loongson_machine_type {
+ MACH_LOONGSON_UNKNOWN,
+ MACH_LEMOTE_FL2E,
+ MACH_LEMOTE_FL2F,
+ MACH_LEMOTE_ML2F7,
+ MACH_LEMOTE_YL2F89,
+ MACH_DEXXON_GDIUM2F10,
+ MACH_LEMOTE_NAS,
+ MACH_LEMOTE_LL2F,
+ MACH_LEMOTE_A1004,
+ MACH_LEMOTE_A1101,
+ MACH_LEMOTE_A1201,
+ MACH_LEMOTE_A1205,
+ MACH_LOONGSON_END
+};
/*
* Valid machtype for group INGENIC
@@ -112,6 +118,8 @@ extern void prom_free_prom_memory(void);
extern void free_init_pages(const char *what,
unsigned long begin, unsigned long end);
+extern void (*free_init_pages_eva)(void *begin, void *end);
+
/*
* Initial kernel command line, usually setup by prom_init()
*/
diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h
index e28a3e0eb3c..de781cf54bc 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -8,6 +8,8 @@
#ifndef _ASM_BRANCH_H
#define _ASM_BRANCH_H
+#include <asm/cpu-features.h>
+#include <asm/mipsregs.h>
#include <asm/ptrace.h>
#include <asm/inst.h>
@@ -18,12 +20,40 @@ extern int __compute_return_epc_for_insn(struct pt_regs *regs,
extern int __microMIPS_compute_return_epc(struct pt_regs *regs);
extern int __MIPS16e_compute_return_epc(struct pt_regs *regs);
+/*
+ * microMIPS bitfields
+ */
+#define MM_POOL32A_MINOR_MASK 0x3f
+#define MM_POOL32A_MINOR_SHIFT 0x6
+#define MM_MIPS32_COND_FC 0x30
+
+extern int __mm_isBranchInstr(struct pt_regs *regs,
+ struct mm_decoded_insn dec_insn, unsigned long *contpc);
+
+static inline int mm_isBranchInstr(struct pt_regs *regs,
+ struct mm_decoded_insn dec_insn, unsigned long *contpc)
+{
+ if (!cpu_has_mmips)
+ return 0;
+
+ return __mm_isBranchInstr(regs, dec_insn, contpc);
+}
static inline int delay_slot(struct pt_regs *regs)
{
return regs->cp0_cause & CAUSEF_BD;
}
+static inline void clear_delay_slot(struct pt_regs *regs)
+{
+ regs->cp0_cause &= ~CAUSEF_BD;
+}
+
+static inline void set_delay_slot(struct pt_regs *regs)
+{
+ regs->cp0_cause |= CAUSEF_BD;
+}
+
static inline unsigned long exception_epc(struct pt_regs *regs)
{
if (likely(!delay_slot(regs)))
diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index 69468ded282..e08381a37f8 100644
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -113,6 +113,12 @@ unsigned long run_uncached(void *func);
extern void *kmap_coherent(struct page *page, unsigned long addr);
extern void kunmap_coherent(void);
+extern void *kmap_noncoherent(struct page *page, unsigned long addr);
+
+static inline void kunmap_noncoherent(void)
+{
+ kunmap_coherent();
+}
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
static inline void flush_kernel_dcache_page(struct page *page)
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h
index 68f37e3eccc..06b9bc7ea14 100644
--- a/arch/mips/include/asm/cacheops.h
+++ b/arch/mips/include/asm/cacheops.h
@@ -14,56 +14,52 @@
/*
* Cache Operations available on all MIPS processors with R4000-style caches
*/
-#define Index_Invalidate_I 0x00
-#define Index_Writeback_Inv_D 0x01
-#define Index_Load_Tag_I 0x04
-#define Index_Load_Tag_D 0x05
-#define Index_Store_Tag_I 0x08
-#define Index_Store_Tag_D 0x09
-#if defined(CONFIG_CPU_LOONGSON2)
-#define Hit_Invalidate_I 0x00
-#else
-#define Hit_Invalidate_I 0x10
-#endif
-#define Hit_Invalidate_D 0x11
-#define Hit_Writeback_Inv_D 0x15
+#define Index_Invalidate_I 0x00
+#define Index_Writeback_Inv_D 0x01
+#define Index_Load_Tag_I 0x04
+#define Index_Load_Tag_D 0x05
+#define Index_Store_Tag_I 0x08
+#define Index_Store_Tag_D 0x09
+#define Hit_Invalidate_I 0x10
+#define Hit_Invalidate_D 0x11
+#define Hit_Writeback_Inv_D 0x15
/*
* R4000-specific cacheops
*/
-#define Create_Dirty_Excl_D 0x0d
-#define Fill 0x14
-#define Hit_Writeback_I 0x18
-#define Hit_Writeback_D 0x19
+#define Create_Dirty_Excl_D 0x0d
+#define Fill 0x14
+#define Hit_Writeback_I 0x18
+#define Hit_Writeback_D 0x19
/*
* R4000SC and R4400SC-specific cacheops
*/
-#define Index_Invalidate_SI 0x02
-#define Index_Writeback_Inv_SD 0x03
-#define Index_Load_Tag_SI 0x06
-#define Index_Load_Tag_SD 0x07
-#define Index_Store_Tag_SI 0x0A
-#define Index_Store_Tag_SD 0x0B
-#define Create_Dirty_Excl_SD 0x0f
-#define Hit_Invalidate_SI 0x12
-#define Hit_Invalidate_SD 0x13
-#define Hit_Writeback_Inv_SD 0x17
-#define Hit_Writeback_SD 0x1b
-#define Hit_Set_Virtual_SI 0x1e
-#define Hit_Set_Virtual_SD 0x1f
+#define Index_Invalidate_SI 0x02
+#define Index_Writeback_Inv_SD 0x03
+#define Index_Load_Tag_SI 0x06
+#define Index_Load_Tag_SD 0x07
+#define Index_Store_Tag_SI 0x0A
+#define Index_Store_Tag_SD 0x0B
+#define Create_Dirty_Excl_SD 0x0f
+#define Hit_Invalidate_SI 0x12
+#define Hit_Invalidate_SD 0x13
+#define Hit_Writeback_Inv_SD 0x17
+#define Hit_Writeback_SD 0x1b
+#define Hit_Set_Virtual_SI 0x1e
+#define Hit_Set_Virtual_SD 0x1f
/*
* R5000-specific cacheops
*/
-#define R5K_Page_Invalidate_S 0x17
+#define R5K_Page_Invalidate_S 0x17
/*
* RM7000-specific cacheops
*/
-#define Page_Invalidate_T 0x16
-#define Index_Store_Tag_T 0x0a
-#define Index_Load_Tag_T 0x06
+#define Page_Invalidate_T 0x16
+#define Index_Store_Tag_T 0x0a
+#define Index_Load_Tag_T 0x06
/*
* R10000-specific cacheops
@@ -71,17 +67,22 @@
* Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
* Most of the _S cacheops are identical to the R4000SC _SD cacheops.
*/
-#define Index_Writeback_Inv_S 0x03
-#define Index_Load_Tag_S 0x07
-#define Index_Store_Tag_S 0x0B
-#define Hit_Invalidate_S 0x13
-#define Cache_Barrier 0x14
-#define Hit_Writeback_Inv_S 0x17
-#define Index_Load_Data_I 0x18
-#define Index_Load_Data_D 0x19
-#define Index_Load_Data_S 0x1b
-#define Index_Store_Data_I 0x1c
-#define Index_Store_Data_D 0x1d
-#define Index_Store_Data_S 0x1f
+#define Index_Writeback_Inv_S 0x03
+#define Index_Load_Tag_S 0x07
+#define Index_Store_Tag_S 0x0B
+#define Hit_Invalidate_S 0x13
+#define Cache_Barrier 0x14
+#define Hit_Writeback_Inv_S 0x17
+#define Index_Load_Data_I 0x18
+#define Index_Load_Data_D 0x19
+#define Index_Load_Data_S 0x1b
+#define Index_Store_Data_I 0x1c
+#define Index_Store_Data_D 0x1d
+#define Index_Store_Data_S 0x1f
+
+/*
+ * Loongson2-specific cacheops
+ */
+#define Hit_Invalidate_I_Loongson2 0x00
#endif /* __ASM_CACHEOPS_H */
diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h
index ac3d2b8a20d..3418c51e115 100644
--- a/arch/mips/include/asm/checksum.h
+++ b/arch/mips/include/asm/checksum.h
@@ -7,6 +7,7 @@
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) 2001 Thiemo Seufer.
* Copyright (C) 2002 Maciej W. Rozycki
+ * Copyright (C) 2014 Imagination Technologies Ltd.
*/
#ifndef _ASM_CHECKSUM_H
#define _ASM_CHECKSUM_H
@@ -29,9 +30,13 @@
*/
__wsum csum_partial(const void *buff, int len, __wsum sum);
-__wsum __csum_partial_copy_user(const void *src, void *dst,
- int len, __wsum sum, int *err_ptr);
+__wsum __csum_partial_copy_kernel(const void *src, void *dst,
+ int len, __wsum sum, int *err_ptr);
+__wsum __csum_partial_copy_from_user(const void *src, void *dst,
+ int len, __wsum sum, int *err_ptr);
+__wsum __csum_partial_copy_to_user(const void *src, void *dst,
+ int len, __wsum sum, int *err_ptr);
/*
* this is a new version of the above that records errors it finds in *errp,
* but continues and zeros the rest of the buffer.
@@ -41,8 +46,26 @@ __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
__wsum sum, int *err_ptr)
{
might_fault();
- return __csum_partial_copy_user((__force void *)src, dst,
- len, sum, err_ptr);
+ if (segment_eq(get_fs(), get_ds()))
+ return __csum_partial_copy_kernel((__force void *)src, dst,
+ len, sum, err_ptr);
+ else
+ return __csum_partial_copy_from_user((__force void *)src, dst,
+ len, sum, err_ptr);
+}
+
+#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+static inline
+__wsum csum_and_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
+{
+ if (access_ok(VERIFY_READ, src, len))
+ return csum_partial_copy_from_user(src, dst, len, sum,
+ err_ptr);
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return sum;
}
/*
@@ -54,9 +77,16 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
__wsum sum, int *err_ptr)
{
might_fault();
- if (access_ok(VERIFY_WRITE, dst, len))
- return __csum_partial_copy_user(src, (__force void *)dst,
- len, sum, err_ptr);
+ if (access_ok(VERIFY_WRITE, dst, len)) {
+ if (segment_eq(get_fs(), get_ds()))
+ return __csum_partial_copy_kernel(src,
+ (__force void *)dst,
+ len, sum, err_ptr);
+ else
+ return __csum_partial_copy_to_user(src,
+ (__force void *)dst,
+ len, sum, err_ptr);
+ }
if (len)
*err_ptr = -EFAULT;
diff --git a/arch/mips/include/asm/clkdev.h b/arch/mips/include/asm/clkdev.h
index 262475414e5..1b3ad7b09dc 100644
--- a/arch/mips/include/asm/clkdev.h
+++ b/arch/mips/include/asm/clkdev.h
@@ -14,8 +14,10 @@
#include <linux/slab.h>
+#ifndef CONFIG_COMMON_CLK
#define __clk_get(clk) ({ 1; })
#define __clk_put(clk) do { } while (0)
+#endif
static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
{
diff --git a/arch/mips/include/asm/cmp.h b/arch/mips/include/asm/cmp.h
index 89a73fb93ae..033d97303c8 100644
--- a/arch/mips/include/asm/cmp.h
+++ b/arch/mips/include/asm/cmp.h
@@ -10,7 +10,6 @@ extern void cmp_smp_setup(void);
extern void cmp_smp_finish(void);
extern void cmp_boot_secondary(int cpu, struct task_struct *t);
extern void cmp_init_secondary(void);
-extern void cmp_cpus_done(void);
extern void cmp_prepare_cpus(unsigned int max_cpus);
/* This is platform specific */
diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h
index 466069bd846..eefcaa363a8 100644
--- a/arch/mips/include/asm/cmpxchg.h
+++ b/arch/mips/include/asm/cmpxchg.h
@@ -22,11 +22,11 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
unsigned long dummy;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %0, %3 # xchg_u32 \n"
" .set mips0 \n"
" move %2, %z4 \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" sc %2, %1 \n"
" beqzl %2, 1b \n"
" .set mips0 \n"
@@ -38,11 +38,11 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" ll %0, %3 # xchg_u32 \n"
" .set mips0 \n"
" move %2, %z4 \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" sc %2, %1 \n"
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
@@ -74,7 +74,7 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
unsigned long dummy;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: lld %0, %3 # xchg_u64 \n"
" move %2, %z4 \n"
" scd %2, %1 \n"
@@ -88,7 +88,7 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
do {
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" lld %0, %3 # xchg_u64 \n"
" move %2, %z4 \n"
" scd %2, %1 \n"
@@ -145,12 +145,12 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
__asm__ __volatile__( \
" .set push \n" \
" .set noat \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
"1: " ld " %0, %2 # __cmpxchg_asm \n" \
" bne %0, %z3, 2f \n" \
" .set mips0 \n" \
" move $1, %z4 \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
" " st " $1, %1 \n" \
" beqzl $1, 1b \n" \
"2: \n" \
@@ -162,12 +162,12 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
__asm__ __volatile__( \
" .set push \n" \
" .set noat \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
"1: " ld " %0, %2 # __cmpxchg_asm \n" \
" bne %0, %z3, 2f \n" \
" .set mips0 \n" \
" move $1, %z4 \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
" " st " $1, %1 \n" \
" beqz $1, 1b \n" \
" .set pop \n" \
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index fa44f3ec530..c7d8c997d93 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -13,12 +13,6 @@
#include <asm/cpu-info.h>
#include <cpu-feature-overrides.h>
-#ifndef current_cpu_type
-#define current_cpu_type() current_cpu_data.cputype
-#endif
-
-#define boot_cpu_type() cpu_data[0].cputype
-
/*
* SMP assumption: Options of CPU 0 are a superset of all processors.
* This is true for all known MIPS systems.
@@ -26,6 +20,15 @@
#ifndef cpu_has_tlb
#define cpu_has_tlb (cpu_data[0].options & MIPS_CPU_TLB)
#endif
+#ifndef cpu_has_tlbinv
+#define cpu_has_tlbinv (cpu_data[0].options & MIPS_CPU_TLBINV)
+#endif
+#ifndef cpu_has_segments
+#define cpu_has_segments (cpu_data[0].options & MIPS_CPU_SEGMENTS)
+#endif
+#ifndef cpu_has_eva
+#define cpu_has_eva (cpu_data[0].options & MIPS_CPU_EVA)
+#endif
/*
* For the moment we don't consider R6000 and R8000 so we can assume that
@@ -107,9 +110,15 @@
#ifndef cpu_has_smartmips
#define cpu_has_smartmips (cpu_data[0].ases & MIPS_ASE_SMARTMIPS)
#endif
+
#ifndef cpu_has_rixi
-#define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_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
#endif
+
#ifndef cpu_has_mmips
# ifdef CONFIG_SYS_SUPPORTS_MICROMIPS
# define cpu_has_mmips (cpu_data[0].options & MIPS_CPU_MICROMIPS)
@@ -117,6 +126,7 @@
# define cpu_has_mmips 0
# endif
#endif
+
#ifndef cpu_has_vtag_icache
#define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG)
#endif
@@ -180,6 +190,17 @@
/*
* Shortcuts ...
*/
+#define cpu_has_mips_2_3_4_5 (cpu_has_mips_2 | cpu_has_mips_3_4_5)
+#define cpu_has_mips_3_4_5 (cpu_has_mips_3 | cpu_has_mips_4_5)
+#define cpu_has_mips_4_5 (cpu_has_mips_4 | cpu_has_mips_5)
+
+#define cpu_has_mips_2_3_4_5_r (cpu_has_mips_2 | cpu_has_mips_3_4_5_r)
+#define cpu_has_mips_3_4_5_r (cpu_has_mips_3 | cpu_has_mips_4_5_r)
+#define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r)
+#define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r)
+
+#define cpu_has_mips_4_5_r2 (cpu_has_mips_4_5 | cpu_has_mips_r2)
+
#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2)
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2)
#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
@@ -193,7 +214,7 @@
/*
* MIPS32, MIPS64, VR5500, IDT32332, IDT32334 and maybe a few other
- * pre-MIPS32/MIPS53 processors have CLO, CLZ. The IDT RC64574 is 64-bit and
+ * pre-MIPS32/MIPS64 processors have CLO, CLZ. The IDT RC64574 is 64-bit and
* has CLO and CLZ but not DCLO nor DCLZ. For 64-bit kernels
* cpu_has_clo_clz also indicates the availability of DCLO and DCLZ.
*/
@@ -298,4 +319,10 @@
#define cpu_has_vz (cpu_data[0].ases & MIPS_ASE_VZ)
#endif
+#if defined(CONFIG_CPU_HAS_MSA) && !defined(cpu_has_msa)
+# define cpu_has_msa (cpu_data[0].ases & MIPS_ASE_MSA)
+#elif !defined(cpu_has_msa)
+# define cpu_has_msa 0
+#endif
+
#endif /* __ASM_CPU_FEATURES_H */
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index 41401d8eb7d..47d5967ce7e 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -39,19 +39,23 @@ struct cache_desc {
#define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */
struct cpuinfo_mips {
- unsigned int udelay_val;
- unsigned int asid_cache;
+ unsigned long asid_cache;
/*
* Capability and feature descriptor structure for MIPS CPU
*/
unsigned long options;
unsigned long ases;
+ unsigned int udelay_val;
unsigned int processor_id;
unsigned int fpu_id;
+ unsigned int msa_id;
unsigned int cputype;
int isa_level;
int tlbsize;
+ int tlbsizevtlb;
+ int tlbsizeftlbsets;
+ int tlbsizeftlbways;
struct cache_desc icache; /* Primary I-cache */
struct cache_desc dcache; /* Primary D or combined I/D cache */
struct cache_desc scache; /* Secondary cache */
@@ -61,18 +65,13 @@ struct cpuinfo_mips {
#ifdef CONFIG_64BIT
int vmbits; /* Virtual memory size in bits */
#endif
-#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
+#ifdef CONFIG_MIPS_MT_SMP
/*
- * In the MIPS MT "SMTC" model, each TC is considered
- * to be a "CPU" for the purposes of scheduling, but
- * exception resources, ASID spaces, etc, are common
- * to all TCs within the same VPE.
+ * There is not necessarily a 1:1 mapping of VPE num to CPU number
+ * in particular on multi-core systems.
*/
int vpe_id; /* Virtual Processor number */
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
- int tc_id; /* Thread Context number */
-#endif
void *data; /* Additional data */
unsigned int watch_reg_count; /* Number that exist */
unsigned int watch_reg_use_cnt; /* Usable by ptrace */
@@ -84,6 +83,7 @@ struct cpuinfo_mips {
extern struct cpuinfo_mips cpu_data[];
#define current_cpu_data cpu_data[smp_processor_id()]
#define raw_current_cpu_data cpu_data[raw_smp_processor_id()]
+#define boot_cpu_data cpu_data[0]
extern void cpu_probe(void);
extern void cpu_report(void);
@@ -91,4 +91,31 @@ extern void cpu_report(void);
extern const char *__cpu_name[];
#define cpu_name_string() __cpu_name[smp_processor_id()]
+struct seq_file;
+struct notifier_block;
+
+extern int register_proc_cpuinfo_notifier(struct notifier_block *nb);
+extern int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v);
+
+#define proc_cpuinfo_notifier(fn, pri) \
+({ \
+ static struct notifier_block fn##_nb = { \
+ .notifier_call = fn, \
+ .priority = pri \
+ }; \
+ \
+ register_proc_cpuinfo_notifier(&fn##_nb); \
+})
+
+struct proc_cpuinfo_notifier_args {
+ struct seq_file *m;
+ unsigned long n;
+};
+
+#ifdef CONFIG_MIPS_MT_SMP
+# define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id)
+#else
+# define cpu_vpe_id(cpuinfo) 0
+#endif
+
#endif /* __ASM_CPU_INFO_H */
diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
new file mode 100644
index 00000000000..b4e2bd87df5
--- /dev/null
+++ b/arch/mips/include/asm/cpu-type.h
@@ -0,0 +1,216 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 2004 Ralf Baechle
+ * Copyright (C) 2004 Maciej W. Rozycki
+ */
+#ifndef __ASM_CPU_TYPE_H
+#define __ASM_CPU_TYPE_H
+
+#include <linux/smp.h>
+#include <linux/compiler.h>
+
+static inline int __pure __get_cpu_type(const int cpu_type)
+{
+ switch (cpu_type) {
+#if defined(CONFIG_SYS_HAS_CPU_LOONGSON2E) || \
+ defined(CONFIG_SYS_HAS_CPU_LOONGSON2F)
+ case CPU_LOONGSON2:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
+ case CPU_LOONGSON3:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
+ case CPU_LOONGSON1:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R1
+ 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:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R2
+ case CPU_4KSC:
+ case CPU_24K:
+ case CPU_34K:
+ case CPU_1004K:
+ case CPU_74K:
+ case CPU_M14KC:
+ case CPU_M14KEC:
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ case CPU_P5600:
+ case CPU_M5150:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1
+ case CPU_5KC:
+ case CPU_5KE:
+ case CPU_20KC:
+ case CPU_25KF:
+ case CPU_SB1:
+ case CPU_SB1A:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R2
+ /*
+ * All MIPS64 R2 processors have their own special symbols. That is,
+ * there currently is no pure R2 core
+ */
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R3000
+ case CPU_R2000:
+ case CPU_R3000:
+ case CPU_R3000A:
+ case CPU_R3041:
+ case CPU_R3051:
+ case CPU_R3052:
+ case CPU_R3081:
+ case CPU_R3081E:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_TX39XX
+ case CPU_TX3912:
+ case CPU_TX3922:
+ case CPU_TX3927:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_VR41XX
+ case CPU_VR41XX:
+ case CPU_VR4111:
+ case CPU_VR4121:
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ case CPU_VR4181:
+ case CPU_VR4181A:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R4300
+ case CPU_R4300:
+ case CPU_R4310:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R4X00
+ case CPU_R4000PC:
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4200:
+ case CPU_R4400PC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ case CPU_R4600:
+ case CPU_R4700:
+ case CPU_R4640:
+ case CPU_R4650:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_TX49XX
+ case CPU_TX49XX:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R5000
+ case CPU_R5000:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R5432
+ case CPU_R5432:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R5500
+ case CPU_R5500:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R6000
+ case CPU_R6000:
+ case CPU_R6000A:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_NEVADA
+ case CPU_NEVADA:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R8000
+ case CPU_R8000:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R10000
+ case CPU_R10000:
+ case CPU_R12000:
+ case CPU_R14000:
+#endif
+#ifdef CONFIG_SYS_HAS_CPU_RM7000
+ case CPU_RM7000:
+ case CPU_SR71000:
+#endif
+#ifdef CONFIG_SYS_HAS_CPU_SB1
+ case CPU_SB1:
+ case CPU_SB1A:
+#endif
+#ifdef CONFIG_SYS_HAS_CPU_CAVIUM_OCTEON
+ case CPU_CAVIUM_OCTEON:
+ case CPU_CAVIUM_OCTEON_PLUS:
+ case CPU_CAVIUM_OCTEON2:
+ case CPU_CAVIUM_OCTEON3:
+#endif
+
+#if defined(CONFIG_SYS_HAS_CPU_BMIPS32_3300) || \
+ defined (CONFIG_SYS_HAS_CPU_MIPS32_R1)
+ case CPU_BMIPS32:
+ case CPU_BMIPS3300:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_BMIPS4350
+ case CPU_BMIPS4350:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_BMIPS4380
+ case CPU_BMIPS4380:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_BMIPS5000
+ case CPU_BMIPS5000:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_XLP
+ case CPU_XLP:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_XLR
+ case CPU_XLR:
+#endif
+ break;
+ default:
+ unreachable();
+ }
+
+ return cpu_type;
+}
+
+static inline int __pure current_cpu_type(void)
+{
+ const int cpu_type = current_cpu_data.cputype;
+
+ return __get_cpu_type(cpu_type);
+}
+
+static inline int __pure boot_cpu_type(void)
+{
+ const int cpu_type = cpu_data[0].cputype;
+
+ return __get_cpu_type(cpu_type);
+}
+
+#endif /* __ASM_CPU_TYPE_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 71b9f1998be..129d08701e9 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -3,15 +3,14 @@
* various MIPS cpu types.
*
* Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- * Copyright (C) 2004 Maciej W. Rozycki
+ * Copyright (C) 2004, 2013 Maciej W. Rozycki
*/
#ifndef _ASM_CPU_H
#define _ASM_CPU_H
-/* Assigned Company values for bits 23:16 of the PRId Register
- (CP0 register 15, select 0). As of the MIPS32 and MIPS64 specs from
- MTI, the PRId register is defined in this (backwards compatible)
- way:
+/*
+ As of the MIPS32 and MIPS64 specs from MTI, the PRId register (CP0
+ register 15, select 0) is defined in this (backwards compatible) way:
+----------------+----------------+----------------+----------------+
| Company Options| Company ID | Processor ID | Revision |
@@ -23,6 +22,14 @@
spec.
*/
+#define PRID_OPT_MASK 0xff000000
+
+/*
+ * Assigned Company values for bits 23:16 of the PRId register.
+ */
+
+#define PRID_COMP_MASK 0xff0000
+
#define PRID_COMP_LEGACY 0x000000
#define PRID_COMP_MIPS 0x010000
#define PRID_COMP_BROADCOM 0x020000
@@ -38,10 +45,17 @@
#define PRID_COMP_INGENIC 0xd00000
/*
- * Assigned values for the product ID register. In order to detect a
- * certain CPU type exactly eventually additional registers may need to
- * be examined. These are valid when 23:16 == PRID_COMP_LEGACY
+ * Assigned Processor ID (implementation) values for bits 15:8 of the PRId
+ * register. In order to detect a certain CPU type exactly eventually
+ * additional registers may need to be examined.
+ */
+
+#define PRID_IMP_MASK 0xff00
+
+/*
+ * These are valid when 23:16 == PRID_COMP_LEGACY
*/
+
#define PRID_IMP_R2000 0x0100
#define PRID_IMP_AU1_REV1 0x0100
#define PRID_IMP_AU1_REV2 0x0200
@@ -68,10 +82,10 @@
#define PRID_IMP_RM7000 0x2700
#define PRID_IMP_NEVADA 0x2800 /* RM5260 ??? */
#define PRID_IMP_RM9000 0x3400
-#define PRID_IMP_LOONGSON1 0x4200
+#define PRID_IMP_LOONGSON_32 0x4200 /* Loongson-1 */
#define PRID_IMP_R5432 0x5400
#define PRID_IMP_R5500 0x5500
-#define PRID_IMP_LOONGSON2 0x6300
+#define PRID_IMP_LOONGSON_64 0x6300 /* Loongson-2/3 */
#define PRID_IMP_UNKNOWN 0xff00
@@ -97,6 +111,12 @@
#define PRID_IMP_1074K 0x9a00
#define PRID_IMP_M14KC 0x9c00
#define PRID_IMP_M14KEC 0x9e00
+#define PRID_IMP_INTERAPTIV_UP 0xa000
+#define PRID_IMP_INTERAPTIV_MP 0xa100
+#define PRID_IMP_PROAPTIV_UP 0xa200
+#define PRID_IMP_PROAPTIV_MP 0xa300
+#define PRID_IMP_M5150 0xa700
+#define PRID_IMP_P5600 0xa800
/*
* These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -180,13 +200,19 @@
#define PRID_IMP_NETLOGIC_XLP8XX 0x1000
#define PRID_IMP_NETLOGIC_XLP3XX 0x1100
#define PRID_IMP_NETLOGIC_XLP2XX 0x1200
+#define PRID_IMP_NETLOGIC_XLP9XX 0x1500
+#define PRID_IMP_NETLOGIC_XLP5XX 0x1300
/*
- * Definitions for 7:0 on legacy processors
+ * Particular Revision values for bits 7:0 of the PRId register.
*/
#define PRID_REV_MASK 0x00ff
+/*
+ * Definitions for 7:0 on legacy processors
+ */
+
#define PRID_REV_TX4927 0x0022
#define PRID_REV_TX4937 0x0030
#define PRID_REV_R4400 0x0040
@@ -206,6 +232,7 @@
#define PRID_REV_LOONGSON1B 0x0020
#define PRID_REV_LOONGSON2E 0x0002
#define PRID_REV_LOONGSON2F 0x0003
+#define PRID_REV_LOONGSON3A 0x0005
/*
* Older processors used to encode processor version and revision in two
@@ -227,8 +254,12 @@
* 31 16 15 8 7 0
*/
+#define FPIR_IMP_MASK 0xff00
+
#define FPIR_IMP_NONE 0x0000
+#if !defined(__ASSEMBLY__)
+
enum cpu_type_enum {
CPU_UNKNOWN,
@@ -251,7 +282,7 @@ enum cpu_type_enum {
CPU_R4700, CPU_R5000, CPU_R5500, CPU_NEVADA, CPU_R5432, CPU_R10000,
CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, CPU_VR4122,
CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000,
- CPU_SR71000, CPU_RM9000, CPU_TX49XX,
+ CPU_SR71000, CPU_TX49XX,
/*
* R8000 class processors
@@ -269,18 +300,19 @@ enum cpu_type_enum {
CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
- CPU_M14KEC,
+ CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150,
/*
* MIPS64 class processors
*/
CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
- CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2,
- CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
+ CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
+ CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
CPU_LAST
};
+#endif /* !__ASSEMBLY */
/*
* ISA Level encodings
@@ -328,6 +360,9 @@ enum cpu_type_enum {
#define MIPS_CPU_PCI 0x00400000 /* CPU has Perf Ctr Int indicator */
#define MIPS_CPU_RIXI 0x00800000 /* CPU has TLB Read/eXec Inhibit */
#define MIPS_CPU_MICROMIPS 0x01000000 /* CPU has microMIPS capability */
+#define MIPS_CPU_TLBINV 0x02000000 /* CPU supports TLBINV/F */
+#define MIPS_CPU_SEGMENTS 0x04000000 /* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA 0x80000000 /* CPU supports Enhanced Virtual Addressing */
/*
* CPU ASE encodings
@@ -340,5 +375,6 @@ enum cpu_type_enum {
#define MIPS_ASE_MIPSMT 0x00000020 /* CPU supports MIPS MT */
#define MIPS_ASE_DSP2P 0x00000040 /* Signal Processing ASE Rev 2 */
#define MIPS_ASE_VZ 0x00000080 /* Virtualization ASE */
+#define MIPS_ASE_MSA 0x00000100 /* MIPS SIMD Architecture */
#endif /* _ASM_CPU_H */
diff --git a/arch/mips/include/asm/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h
index a6e505a0e44..be4d62a5a10 100644
--- a/arch/mips/include/asm/dec/ioasic.h
+++ b/arch/mips/include/asm/dec/ioasic.h
@@ -31,8 +31,6 @@ static inline u32 ioasic_read(unsigned int reg)
return ioasic_base[reg / 4];
}
-extern void clear_ioasic_dma_irq(unsigned int irq);
-
extern void init_ioasic_irqs(int base);
extern int dec_ioasic_clocksource_init(void);
diff --git a/arch/mips/include/asm/dec/ioasic_addrs.h b/arch/mips/include/asm/dec/ioasic_addrs.h
index a8665a7611c..8bd95971fe2 100644
--- a/arch/mips/include/asm/dec/ioasic_addrs.h
+++ b/arch/mips/include/asm/dec/ioasic_addrs.h
@@ -40,7 +40,7 @@
#define IOASIC_FLOPPY (11*IOASIC_SLOT_SIZE) /* FDC (maxine) */
#define IOASIC_SCSI (12*IOASIC_SLOT_SIZE) /* ASC SCSI */
#define IOASIC_FDC_DMA (13*IOASIC_SLOT_SIZE) /* FDC DMA (maxine) */
-#define IOASIC_SCSI_DMA (14*IOASIC_SLOT_SIZE) /* ??? */
+#define IOASIC_SCSI_DMA (14*IOASIC_SLOT_SIZE) /* ??? */
#define IOASIC_RES_15 (15*IOASIC_SLOT_SIZE) /* unused? */
diff --git a/arch/mips/include/asm/dec/kn01.h b/arch/mips/include/asm/dec/kn01.h
index 0eb3241de70..88d9ffd7425 100644
--- a/arch/mips/include/asm/dec/kn01.h
+++ b/arch/mips/include/asm/dec/kn01.h
@@ -57,12 +57,12 @@
/*
* System Control & Status Register bits.
*/
-#define KN01_CSR_MNFMOD (1<<15) /* MNFMOD manufacturing jumper */
-#define KN01_CSR_STATUS (1<<14) /* self-test result status output */
-#define KN01_CSR_PARDIS (1<<13) /* parity error disable */
-#define KN01_CSR_CRSRTST (1<<12) /* PCC test output */
-#define KN01_CSR_MONO (1<<11) /* mono/color fb SIMM installed */
-#define KN01_CSR_MEMERR (1<<10) /* write timeout error status & ack*/
+#define KN01_CSR_MNFMOD (1<<15) /* MNFMOD manufacturing jumper */
+#define KN01_CSR_STATUS (1<<14) /* self-test result status output */
+#define KN01_CSR_PARDIS (1<<13) /* parity error disable */
+#define KN01_CSR_CRSRTST (1<<12) /* PCC test output */
+#define KN01_CSR_MONO (1<<11) /* mono/color fb SIMM installed */
+#define KN01_CSR_MEMERR (1<<10) /* write timeout error status & ack*/
#define KN01_CSR_VINT (1<<9) /* PCC area detect #2 status & ack */
#define KN01_CSR_TXDIS (1<<8) /* DZ11 transmit disable */
#define KN01_CSR_VBGTRG (1<<2) /* blue DAC voltage over green (r/o) */
diff --git a/arch/mips/include/asm/dec/kn02ca.h b/arch/mips/include/asm/dec/kn02ca.h
index 69dc2a9a2d0..92c0fe25609 100644
--- a/arch/mips/include/asm/dec/kn02ca.h
+++ b/arch/mips/include/asm/dec/kn02ca.h
@@ -68,7 +68,7 @@
#define KN03CA_IO_SSR_ISDN_RST (1<<12) /* ~ISDN (Am79C30A) reset */
#define KN03CA_IO_SSR_FLOPPY_RST (1<<7) /* ~FDC (82077) reset */
-#define KN03CA_IO_SSR_VIDEO_RST (1<<6) /* ~framebuffer reset */
+#define KN03CA_IO_SSR_VIDEO_RST (1<<6) /* ~framebuffer reset */
#define KN03CA_IO_SSR_AB_RST (1<<5) /* ACCESS.bus reset */
#define KN03CA_IO_SSR_RES_4 (1<<4) /* unused */
#define KN03CA_IO_SSR_RES_3 (1<<4) /* unused */
diff --git a/arch/mips/include/asm/dec/kn05.h b/arch/mips/include/asm/dec/kn05.h
index 56d22dc8803..8e14f677e5e 100644
--- a/arch/mips/include/asm/dec/kn05.h
+++ b/arch/mips/include/asm/dec/kn05.h
@@ -49,12 +49,20 @@
#define KN4K_RES_15 (15*IOASIC_SLOT_SIZE) /* unused? */
/*
+ * MB ASIC interrupt bits.
+ */
+#define KN4K_MB_INR_MB 4 /* ??? */
+#define KN4K_MB_INR_MT 3 /* memory, I/O bus read/write errors */
+#define KN4K_MB_INR_RES_2 2 /* unused */
+#define KN4K_MB_INR_RTC 1 /* RTC */
+#define KN4K_MB_INR_TC 0 /* I/O ASIC cascade */
+
+/*
* Bits for the MB interrupt register.
* The register appears read-only.
*/
-#define KN4K_MB_INT_TC (1<<0) /* TURBOchannel? */
-#define KN4K_MB_INT_RTC (1<<1) /* RTC? */
-#define KN4K_MB_INT_MT (1<<3) /* I/O ASIC cascade */
+#define KN4K_MB_INT_IRQ (0x1f<<0) /* CPU Int[4:0] status. */
+#define KN4K_MB_INT_IRQ_N(n) (1<<(n)) /* Individual status bits. */
/*
* Bits for the MB control & status register.
@@ -70,6 +78,7 @@
#define KN4K_MB_CSR_NC (1<<14) /* ??? */
#define KN4K_MB_CSR_EE (1<<15) /* (bus) Exception Enable? */
#define KN4K_MB_CSR_MSK (0x1f<<16) /* CPU Int[4:0] mask */
+#define KN4K_MB_CSR_MSK_N(n) (1<<((n)+16)) /* Individual mask bits. */
#define KN4K_MB_CSR_FW (1<<21) /* ??? */
#define KN4K_MB_CSR_W (1<<31) /* ??? */
diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h
index 446577712be..b59a2103b61 100644
--- a/arch/mips/include/asm/dec/prom.h
+++ b/arch/mips/include/asm/dec/prom.h
@@ -49,7 +49,7 @@
#ifdef CONFIG_64BIT
-#define prom_is_rex(magic) 1 /* KN04 and KN05 are REX PROMs. */
+#define prom_is_rex(magic) 1 /* KN04 and KN05 are REX PROMs. */
#else /* !CONFIG_64BIT */
@@ -113,31 +113,31 @@ extern int (*__pmax_close)(int);
#define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \
__asm__(#fun " = call_o32")
-int __DEC_PROM_O32(_rex_bootinit, (int (*)(void)));
-int __DEC_PROM_O32(_rex_bootread, (int (*)(void)));
-int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), memmap *));
+int __DEC_PROM_O32(_rex_bootinit, (int (*)(void), void *));
+int __DEC_PROM_O32(_rex_bootread, (int (*)(void), void *));
+int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), void *, memmap *));
unsigned long *__DEC_PROM_O32(_rex_slot_address,
- (unsigned long *(*)(int), int));
-void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void)));
-int __DEC_PROM_O32(_rex_getsysid, (int (*)(void)));
-void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void)));
-
-int __DEC_PROM_O32(_prom_getchar, (int (*)(void)));
-char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), char *));
-int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), char *, ...));
-
-
-#define rex_bootinit() _rex_bootinit(__rex_bootinit)
-#define rex_bootread() _rex_bootread(__rex_bootread)
-#define rex_getbitmap(x) _rex_getbitmap(__rex_getbitmap, x)
-#define rex_slot_address(x) _rex_slot_address(__rex_slot_address, x)
-#define rex_gettcinfo() _rex_gettcinfo(__rex_gettcinfo)
-#define rex_getsysid() _rex_getsysid(__rex_getsysid)
-#define rex_clear_cache() _rex_clear_cache(__rex_clear_cache)
-
-#define prom_getchar() _prom_getchar(__prom_getchar)
-#define prom_getenv(x) _prom_getenv(__prom_getenv, x)
-#define prom_printf(x...) _prom_printf(__prom_printf, x)
+ (unsigned long *(*)(int), void *, int));
+void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void), void *));
+int __DEC_PROM_O32(_rex_getsysid, (int (*)(void), void *));
+void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void), void *));
+
+int __DEC_PROM_O32(_prom_getchar, (int (*)(void), void *));
+char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), void *, char *));
+int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), void *, char *, ...));
+
+
+#define rex_bootinit() _rex_bootinit(__rex_bootinit, NULL)
+#define rex_bootread() _rex_bootread(__rex_bootread, NULL)
+#define rex_getbitmap(x) _rex_getbitmap(__rex_getbitmap, NULL, x)
+#define rex_slot_address(x) _rex_slot_address(__rex_slot_address, NULL, x)
+#define rex_gettcinfo() _rex_gettcinfo(__rex_gettcinfo, NULL)
+#define rex_getsysid() _rex_getsysid(__rex_getsysid, NULL)
+#define rex_clear_cache() _rex_clear_cache(__rex_clear_cache, NULL)
+
+#define prom_getchar() _prom_getchar(__prom_getchar, NULL)
+#define prom_getenv(x) _prom_getenv(__prom_getenv, NULL, x)
+#define prom_printf(x...) _prom_printf(__prom_printf, NULL, x)
#else /* !CONFIG_64BIT */
diff --git a/arch/mips/include/asm/dma-coherence.h b/arch/mips/include/asm/dma-coherence.h
index 242cbb3ca58..bc5e85d579e 100644
--- a/arch/mips/include/asm/dma-coherence.h
+++ b/arch/mips/include/asm/dma-coherence.h
@@ -9,7 +9,16 @@
#ifndef __ASM_DMA_COHERENCE_H
#define __ASM_DMA_COHERENCE_H
+#ifdef CONFIG_DMA_MAYBE_COHERENT
extern int coherentio;
extern int hw_coherentio;
+#else
+#ifdef CONFIG_DMA_COHERENT
+#define coherentio 1
+#else
+#define coherentio 0
+#endif
+#define hw_coherentio 0
+#endif /* CONFIG_DMA_MAYBE_COHERENT */
#endif
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index 84238c574d5..06412aa9e3f 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device *dev, u64 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;
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index cf3ae2480b1..d4144056e92 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -36,6 +36,7 @@
#define EF_MIPS_ABI2 0x00000020
#define EF_MIPS_OPTIONS_FIRST 0x00000080
#define EF_MIPS_32BITMODE 0x00000100
+#define EF_MIPS_FP64 0x00000200
#define EF_MIPS_ABI 0x0000f000
#define EF_MIPS_ARCH 0xf0000000
@@ -176,6 +177,18 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#ifdef CONFIG_32BIT
/*
+ * In order to be sure that we don't attempt to execute an O32 binary which
+ * requires 64 bit FP (FR=1) on a system which does not support it we refuse
+ * to execute any binary which has bits specified by the following macro set
+ * in its ELF header flags.
+ */
+#ifdef CONFIG_MIPS_O32_FP64_SUPPORT
+# define __MIPS_O32_FP64_MUST_BE_ZERO 0
+#else
+# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64
+#endif
+
+/*
* This is used to ensure we don't load something for the wrong architecture.
*/
#define elf_check_arch(hdr) \
@@ -192,6 +205,8 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
if (((__h->e_flags & EF_MIPS_ABI) != 0) && \
((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \
__res = 0; \
+ if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \
+ __res = 0; \
\
__res; \
})
@@ -249,6 +264,11 @@ extern struct mips_abi mips_abi_n32;
#define SET_PERSONALITY(ex) \
do { \
+ if ((ex).e_flags & EF_MIPS_FP64) \
+ clear_thread_flag(TIF_32BIT_FPREGS); \
+ else \
+ set_thread_flag(TIF_32BIT_FPREGS); \
+ \
if (personality(current->personality) != PER_LINUX) \
set_personality(PER_LINUX); \
\
@@ -271,14 +291,18 @@ do { \
#endif
#ifdef CONFIG_MIPS32_O32
-#define __SET_PERSONALITY32_O32() \
+#define __SET_PERSONALITY32_O32(ex) \
do { \
set_thread_flag(TIF_32BIT_REGS); \
set_thread_flag(TIF_32BIT_ADDR); \
+ \
+ if (!((ex).e_flags & EF_MIPS_FP64)) \
+ set_thread_flag(TIF_32BIT_FPREGS); \
+ \
current->thread.abi = &mips_abi_32; \
} while (0)
#else
-#define __SET_PERSONALITY32_O32() \
+#define __SET_PERSONALITY32_O32(ex) \
do { } while (0)
#endif
@@ -289,7 +313,7 @@ do { \
((ex).e_flags & EF_MIPS_ABI) == 0) \
__SET_PERSONALITY32_N32(); \
else \
- __SET_PERSONALITY32_O32(); \
+ __SET_PERSONALITY32_O32(ex); \
} while (0)
#else
#define __SET_PERSONALITY32(ex) do { } while (0)
@@ -300,6 +324,7 @@ do { \
unsigned int p; \
\
clear_thread_flag(TIF_32BIT_REGS); \
+ clear_thread_flag(TIF_32BIT_FPREGS); \
clear_thread_flag(TIF_32BIT_ADDR); \
\
if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
@@ -331,6 +356,7 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) \
dump_task_fpu(tsk, elf_fpregs)
+#define CORE_DUMP_USE_REGSET
#define ELF_EXEC_PAGESIZE PAGE_SIZE
/* This yields a mask that user programs can use to figure out what
diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h
index dfaaf493e9d..6842ffafd1e 100644
--- a/arch/mips/include/asm/fixmap.h
+++ b/arch/mips/include/asm/fixmap.h
@@ -48,11 +48,7 @@
enum fixed_addresses {
#define FIX_N_COLOURS 8
FIX_CMAP_BEGIN,
-#ifdef CONFIG_MIPS_MT_SMTC
- FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS * 2),
-#else
FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * 2),
-#endif
#ifdef CONFIG_HIGHMEM
/* reserved pte's for temporary kernel mappings */
FIX_KMAP_BEGIN = FIX_CMAP_END + 1,
@@ -71,38 +67,7 @@ enum fixed_addresses {
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
-#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
-#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
-
-extern void __this_fixmap_does_not_exist(void);
-
-/*
- * 'index to address' translation. If anyone tries to use the idx
- * directly without tranlation, we catch the bug with a NULL-deference
- * kernel oops. Illegal ranges of incoming indices are caught too.
- */
-static inline unsigned long fix_to_virt(const unsigned int idx)
-{
- /*
- * this branch gets completely eliminated after inlining,
- * except when someone tries to use fixaddr indices in an
- * illegal way. (such as mixing up address types or using
- * out-of-range indices).
- *
- * If it doesn't get removed, the linker will complain
- * loudly with a reasonably clear error message..
- */
- if (idx >= __end_of_fixed_addresses)
- __this_fixmap_does_not_exist();
-
- return __fix_to_virt(idx);
-}
-
-static inline unsigned long virt_to_fix(const unsigned long vaddr)
-{
- BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
- return __virt_to_fix(vaddr);
-}
+#include <asm-generic/fixmap.h>
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index d088e5db490..a939574f829 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -17,6 +17,7 @@
#include <asm/mipsregs.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
+#include <asm/fpu_emulator.h>
#include <asm/hazards.h>
#include <asm/processor.h>
#include <asm/current.h>
@@ -28,16 +29,54 @@
struct sigcontext;
struct sigcontext32;
-extern void fpu_emulator_init_fpu(void);
extern void _init_fpu(void);
extern void _save_fp(struct task_struct *);
extern void _restore_fp(struct task_struct *);
-#define __enable_fpu() \
-do { \
- set_c0_status(ST0_CU1); \
- enable_fpu_hazard(); \
-} while (0)
+/*
+ * This enum specifies a mode in which we want the FPU to operate, for cores
+ * which implement the Status.FR bit. Note that FPU_32BIT & FPU_64BIT
+ * purposefully have the values 0 & 1 respectively, so that an integer value
+ * of Status.FR can be trivially casted to the corresponding enum fpu_mode.
+ */
+enum fpu_mode {
+ FPU_32BIT = 0, /* FR = 0 */
+ FPU_64BIT, /* FR = 1 */
+ FPU_AS_IS,
+};
+
+static inline int __enable_fpu(enum fpu_mode mode)
+{
+ int fr;
+
+ switch (mode) {
+ case FPU_AS_IS:
+ /* just enable the FPU in its current mode */
+ set_c0_status(ST0_CU1);
+ enable_fpu_hazard();
+ return 0;
+
+ case FPU_64BIT:
+#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
+ /* we only have a 32-bit FPU */
+ return SIGFPE;
+#endif
+ /* fall through */
+ case FPU_32BIT:
+ /* set CU1 & change FR appropriately */
+ fr = (int)mode;
+ change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0));
+ enable_fpu_hazard();
+
+ /* check FR has the desired value */
+ return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE;
+
+ default:
+ BUG();
+ }
+
+ return SIGFPE;
+}
#define __disable_fpu() \
do { \
@@ -45,19 +84,6 @@ do { \
disable_fpu_hazard(); \
} while (0)
-#define enable_fpu() \
-do { \
- if (cpu_has_fpu) \
- __enable_fpu(); \
-} while (0)
-
-#define disable_fpu() \
-do { \
- if (cpu_has_fpu) \
- __disable_fpu(); \
-} while (0)
-
-
#define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU)
static inline int __is_fpu_owner(void)
@@ -70,27 +96,46 @@ static inline int is_fpu_owner(void)
return cpu_has_fpu && __is_fpu_owner();
}
-static inline void __own_fpu(void)
+static inline int __own_fpu(void)
{
- __enable_fpu();
+ enum fpu_mode mode;
+ int ret;
+
+ mode = !test_thread_flag(TIF_32BIT_FPREGS);
+ ret = __enable_fpu(mode);
+ if (ret)
+ return ret;
+
KSTK_STATUS(current) |= ST0_CU1;
+ if (mode == FPU_64BIT)
+ KSTK_STATUS(current) |= ST0_FR;
+ else /* mode == FPU_32BIT */
+ KSTK_STATUS(current) &= ~ST0_FR;
+
set_thread_flag(TIF_USEDFPU);
+ return 0;
}
-static inline void own_fpu_inatomic(int restore)
+static inline int own_fpu_inatomic(int restore)
{
+ int ret = 0;
+
if (cpu_has_fpu && !__is_fpu_owner()) {
- __own_fpu();
- if (restore)
+ ret = __own_fpu();
+ if (restore && !ret)
_restore_fp(current);
}
+ return ret;
}
-static inline void own_fpu(int restore)
+static inline int own_fpu(int restore)
{
+ int ret;
+
preempt_disable();
- own_fpu_inatomic(restore);
+ ret = own_fpu_inatomic(restore);
preempt_enable();
+ return ret;
}
static inline void lose_fpu(int save)
@@ -106,16 +151,22 @@ static inline void lose_fpu(int save)
preempt_enable();
}
-static inline void init_fpu(void)
+static inline int init_fpu(void)
{
+ int ret = 0;
+
preempt_disable();
+
if (cpu_has_fpu) {
- __own_fpu();
- _init_fpu();
- } else {
+ ret = __own_fpu();
+ if (!ret)
+ _init_fpu();
+ } else
fpu_emulator_init_fpu();
- }
+
preempt_enable();
+
+ return ret;
}
static inline void save_fp(struct task_struct *tsk)
@@ -130,7 +181,7 @@ static inline void restore_fp(struct task_struct *tsk)
_restore_fp(tsk);
}
-static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
+static inline union fpureg *get_fpu_regs(struct task_struct *tsk)
{
if (tsk == current) {
preempt_disable();
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index 2abb587d5ab..0195745b4b1 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -23,9 +23,12 @@
#ifndef _ASM_FPU_EMULATOR_H
#define _ASM_FPU_EMULATOR_H
+#include <linux/sched.h>
#include <asm/break.h>
+#include <asm/thread_info.h>
#include <asm/inst.h>
#include <asm/local.h>
+#include <asm/processor.h>
#ifdef CONFIG_DEBUG_FS
@@ -36,6 +39,11 @@ struct mips_fpu_emulator_stats {
local_t cp1ops;
local_t cp1xops;
local_t errors;
+ local_t ieee754_inexact;
+ local_t ieee754_underflow;
+ local_t ieee754_overflow;
+ local_t ieee754_zerodiv;
+ local_t ieee754_invalidop;
};
DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
@@ -71,4 +79,17 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
*/
#define BREAK_MATH (0x0000000d | (BRK_MEMU << 16))
+#define SIGNALLING_NAN 0x7ff800007ff80000LL
+
+static inline void fpu_emulator_init_fpu(void)
+{
+ struct task_struct *t = current;
+ int i;
+
+ t->thread.fpu.fcr31 = 0;
+
+ for (i = 0; i < 32; i++)
+ set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN);
+}
+
#endif /* _ASM_FPU_EMULATOR_H */
diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index ce35c9af0c2..992aaba603b 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -22,12 +22,12 @@ extern void _mcount(void);
#define safe_load(load, src, dst, error) \
do { \
asm volatile ( \
- "1: " load " %[" STR(dst) "], 0(%[" STR(src) "])\n"\
- " li %[" STR(error) "], 0\n" \
+ "1: " load " %[tmp_dst], 0(%[tmp_src])\n" \
+ " li %[tmp_err], 0\n" \
"2:\n" \
\
".section .fixup, \"ax\"\n" \
- "3: li %[" STR(error) "], 1\n" \
+ "3: li %[tmp_err], 1\n" \
" j 2b\n" \
".previous\n" \
\
@@ -35,8 +35,8 @@ do { \
STR(PTR) "\t1b, 3b\n\t" \
".previous\n" \
\
- : [dst] "=&r" (dst), [error] "=r" (error)\
- : [src] "r" (src) \
+ : [tmp_dst] "=&r" (dst), [tmp_err] "=r" (error)\
+ : [tmp_src] "r" (src) \
: "memory" \
); \
} while (0)
@@ -44,12 +44,12 @@ do { \
#define safe_store(store, src, dst, error) \
do { \
asm volatile ( \
- "1: " store " %[" STR(src) "], 0(%[" STR(dst) "])\n"\
- " li %[" STR(error) "], 0\n" \
+ "1: " store " %[tmp_src], 0(%[tmp_dst])\n"\
+ " li %[tmp_err], 0\n" \
"2:\n" \
\
".section .fixup, \"ax\"\n" \
- "3: li %[" STR(error) "], 1\n" \
+ "3: li %[tmp_err], 1\n" \
" j 2b\n" \
".previous\n" \
\
@@ -57,8 +57,8 @@ do { \
STR(PTR) "\t1b, 3b\n\t" \
".previous\n" \
\
- : [error] "=r" (error) \
- : [dst] "r" (dst), [src] "r" (src)\
+ : [tmp_err] "=r" (error) \
+ : [tmp_dst] "r" (dst), [tmp_src] "r" (src)\
: "memory" \
); \
} while (0)
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index 6ea15815d3e..194cda0396a 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -12,6 +12,7 @@
#include <linux/futex.h>
#include <linux/uaccess.h>
+#include <asm/asm-eva.h>
#include <asm/barrier.h>
#include <asm/errno.h>
#include <asm/war.h>
@@ -22,11 +23,11 @@
__asm__ __volatile__( \
" .set push \n" \
" .set noat \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
"1: ll %1, %4 # __futex_atomic_op \n" \
" .set mips0 \n" \
" " insn " \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
"2: sc $1, %2 \n" \
" beqzl $1, 1b \n" \
__WEAK_LLSC_MB \
@@ -48,12 +49,12 @@
__asm__ __volatile__( \
" .set push \n" \
" .set noat \n" \
- " .set mips3 \n" \
- "1: ll %1, %4 # __futex_atomic_op \n" \
+ " .set arch=r4000 \n" \
+ "1: "user_ll("%1", "%4")" # __futex_atomic_op\n" \
" .set mips0 \n" \
" " insn " \n" \
- " .set mips3 \n" \
- "2: sc $1, %2 \n" \
+ " .set arch=r4000 \n" \
+ "2: "user_sc("$1", "%2")" \n" \
" beqz $1, 1b \n" \
__WEAK_LLSC_MB \
"3: \n" \
@@ -146,12 +147,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
"# futex_atomic_cmpxchg_inatomic \n"
" .set push \n"
" .set noat \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %1, %3 \n"
" bne %1, %z4, 3f \n"
" .set mips0 \n"
" move $1, %z5 \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"2: sc $1, %2 \n"
" beqzl $1, 1b \n"
__WEAK_LLSC_MB
@@ -173,13 +174,13 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
"# futex_atomic_cmpxchg_inatomic \n"
" .set push \n"
" .set noat \n"
- " .set mips3 \n"
- "1: ll %1, %3 \n"
+ " .set arch=r4000 \n"
+ "1: "user_ll("%1", "%3")" \n"
" bne %1, %z4, 3f \n"
" .set mips0 \n"
" move $1, %z5 \n"
- " .set mips3 \n"
- "2: sc $1, %2 \n"
+ " .set arch=r4000 \n"
+ "2: "user_sc("$1", "%2")" \n"
" beqz $1, 1b \n"
__WEAK_LLSC_MB
"3: \n"
diff --git a/arch/mips/include/asm/fw/fw.h b/arch/mips/include/asm/fw/fw.h
index d6c50a7e9ed..f3e6978aad7 100644
--- a/arch/mips/include/asm/fw/fw.h
+++ b/arch/mips/include/asm/fw/fw.h
@@ -38,7 +38,7 @@ extern int *_fw_envp;
extern void fw_init_cmdline(void);
extern char *fw_getcmdline(void);
-extern fw_memblock_t *fw_getmdesc(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/arch/mips/include/asm/gcmpregs.h b/arch/mips/include/asm/gcmpregs.h
deleted file mode 100644
index a7359f77a48..00000000000
--- a/arch/mips/include/asm/gcmpregs.h
+++ /dev/null
@@ -1,125 +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) 2000, 07 MIPS Technologies, Inc.
- *
- * Multiprocessor Subsystem Register Definitions
- *
- */
-#ifndef _ASM_GCMPREGS_H
-#define _ASM_GCMPREGS_H
-
-
-/* Offsets to major blocks within GCMP from GCMP base */
-#define GCMP_GCB_OFS 0x0000 /* Global Control Block */
-#define GCMP_CLCB_OFS 0x2000 /* Core Local Control Block */
-#define GCMP_COCB_OFS 0x4000 /* Core Other Control Block */
-#define GCMP_GDB_OFS 0x8000 /* Global Debug Block */
-
-/* Offsets to individual GCMP registers from GCMP base */
-#define GCMPOFS(block, tag, reg) \
- (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
-#define GCMPOFSn(block, tag, reg, n) \
- (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS(n))
-
-#define GCMPGCBOFS(reg) GCMPOFS(GCB, GCB, reg)
-#define GCMPGCBOFSn(reg, n) GCMPOFSn(GCB, GCB, reg, n)
-#define GCMPCLCBOFS(reg) GCMPOFS(CLCB, CCB, reg)
-#define GCMPCOCBOFS(reg) GCMPOFS(COCB, CCB, reg)
-#define GCMPGDBOFS(reg) GCMPOFS(GDB, GDB, reg)
-
-/* GCMP register access */
-#define GCMPGCB(reg) REGP(_gcmp_base, GCMPGCBOFS(reg))
-#define GCMPGCBn(reg, n) REGP(_gcmp_base, GCMPGCBOFSn(reg, n))
-#define GCMPCLCB(reg) REGP(_gcmp_base, GCMPCLCBOFS(reg))
-#define GCMPCOCB(reg) REGP(_gcmp_base, GCMPCOCBOFS(reg))
-#define GCMPGDB(reg) REGP(_gcmp_base, GCMPGDBOFS(reg))
-
-/* Mask generation */
-#define GCMPMSK(block, reg, bits) (MSK(bits)<<GCMP_##block##_##reg##_SHF)
-#define GCMPGCBMSK(reg, bits) GCMPMSK(GCB, reg, bits)
-#define GCMPCCBMSK(reg, bits) GCMPMSK(CCB, reg, bits)
-#define GCMPGDBMSK(reg, bits) GCMPMSK(GDB, reg, bits)
-
-/* GCB registers */
-#define GCMP_GCB_GC_OFS 0x0000 /* Global Config Register */
-#define GCMP_GCB_GC_NUMIOCU_SHF 8
-#define GCMP_GCB_GC_NUMIOCU_MSK GCMPGCBMSK(GC_NUMIOCU, 4)
-#define GCMP_GCB_GC_NUMCORES_SHF 0
-#define GCMP_GCB_GC_NUMCORES_MSK GCMPGCBMSK(GC_NUMCORES, 8)
-#define GCMP_GCB_GCMPB_OFS 0x0008 /* Global GCMP Base */
-#define GCMP_GCB_GCMPB_GCMPBASE_SHF 15
-#define GCMP_GCB_GCMPB_GCMPBASE_MSK GCMPGCBMSK(GCMPB_GCMPBASE, 17)
-#define GCMP_GCB_GCMPB_CMDEFTGT_SHF 0
-#define GCMP_GCB_GCMPB_CMDEFTGT_MSK GCMPGCBMSK(GCMPB_CMDEFTGT, 2)
-#define GCMP_GCB_GCMPB_CMDEFTGT_DISABLED 0
-#define GCMP_GCB_GCMPB_CMDEFTGT_MEM 1
-#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU1 2
-#define GCMP_GCB_GCMPB_CMDEFTGT_IOCU2 3
-#define GCMP_GCB_CCMC_OFS 0x0010 /* Global CM Control */
-#define GCMP_GCB_GCSRAP_OFS 0x0020 /* Global CSR Access Privilege */
-#define GCMP_GCB_GCSRAP_CMACCESS_SHF 0
-#define GCMP_GCB_GCSRAP_CMACCESS_MSK GCMPGCBMSK(GCSRAP_CMACCESS, 8)
-#define GCMP_GCB_GCMPREV_OFS 0x0030 /* GCMP Revision Register */
-#define GCMP_GCB_GCMEM_OFS 0x0040 /* Global CM Error Mask */
-#define GCMP_GCB_GCMEC_OFS 0x0048 /* Global CM Error Cause */
-#define GCMP_GCB_GMEC_ERROR_TYPE_SHF 27
-#define GCMP_GCB_GMEC_ERROR_TYPE_MSK GCMPGCBMSK(GMEC_ERROR_TYPE, 5)
-#define GCMP_GCB_GMEC_ERROR_INFO_SHF 0
-#define GCMP_GCB_GMEC_ERROR_INFO_MSK GCMPGCBMSK(GMEC_ERROR_INFO, 27)
-#define GCMP_GCB_GCMEA_OFS 0x0050 /* Global CM Error Address */
-#define GCMP_GCB_GCMEO_OFS 0x0058 /* Global CM Error Multiple */
-#define GCMP_GCB_GMEO_ERROR_2ND_SHF 0
-#define GCMP_GCB_GMEO_ERROR_2ND_MSK GCMPGCBMSK(GMEO_ERROR_2ND, 5)
-#define GCMP_GCB_GICBA_OFS 0x0080 /* Global Interrupt Controller Base Address */
-#define GCMP_GCB_GICBA_BASE_SHF 17
-#define GCMP_GCB_GICBA_BASE_MSK GCMPGCBMSK(GICBA_BASE, 15)
-#define GCMP_GCB_GICBA_EN_SHF 0
-#define GCMP_GCB_GICBA_EN_MSK GCMPGCBMSK(GICBA_EN, 1)
-
-/* GCB Regions */
-#define GCMP_GCB_CMxBASE_OFS(n) (0x0090+16*(n)) /* Global Region[0-3] Base Address */
-#define GCMP_GCB_CMxBASE_BASE_SHF 16
-#define GCMP_GCB_CMxBASE_BASE_MSK GCMPGCBMSK(CMxBASE_BASE, 16)
-#define GCMP_GCB_CMxMASK_OFS(n) (0x0098+16*(n)) /* Global Region[0-3] Address Mask */
-#define GCMP_GCB_CMxMASK_MASK_SHF 16
-#define GCMP_GCB_CMxMASK_MASK_MSK GCMPGCBMSK(CMxMASK_MASK, 16)
-#define GCMP_GCB_CMxMASK_CMREGTGT_SHF 0
-#define GCMP_GCB_CMxMASK_CMREGTGT_MSK GCMPGCBMSK(CMxMASK_CMREGTGT, 2)
-#define GCMP_GCB_CMxMASK_CMREGTGT_MEM 0
-#define GCMP_GCB_CMxMASK_CMREGTGT_MEM1 1
-#define GCMP_GCB_CMxMASK_CMREGTGT_IOCU1 2
-#define GCMP_GCB_CMxMASK_CMREGTGT_IOCU2 3
-
-
-/* Core local/Core other control block registers */
-#define GCMP_CCB_RESETR_OFS 0x0000 /* Reset Release */
-#define GCMP_CCB_RESETR_INRESET_SHF 0
-#define GCMP_CCB_RESETR_INRESET_MSK GCMPCCBMSK(RESETR_INRESET, 16)
-#define GCMP_CCB_COHCTL_OFS 0x0008 /* Coherence Control */
-#define GCMP_CCB_COHCTL_DOMAIN_SHF 0
-#define GCMP_CCB_COHCTL_DOMAIN_MSK GCMPCCBMSK(COHCTL_DOMAIN, 8)
-#define GCMP_CCB_CFG_OFS 0x0010 /* Config */
-#define GCMP_CCB_CFG_IOCUTYPE_SHF 10
-#define GCMP_CCB_CFG_IOCUTYPE_MSK GCMPCCBMSK(CFG_IOCUTYPE, 2)
-#define GCMP_CCB_CFG_IOCUTYPE_CPU 0
-#define GCMP_CCB_CFG_IOCUTYPE_NCIOCU 1
-#define GCMP_CCB_CFG_IOCUTYPE_CIOCU 2
-#define GCMP_CCB_CFG_NUMVPE_SHF 0
-#define GCMP_CCB_CFG_NUMVPE_MSK GCMPCCBMSK(CFG_NUMVPE, 10)
-#define GCMP_CCB_OTHER_OFS 0x0018 /* Other Address */
-#define GCMP_CCB_OTHER_CORENUM_SHF 16
-#define GCMP_CCB_OTHER_CORENUM_MSK GCMPCCBMSK(OTHER_CORENUM, 16)
-#define GCMP_CCB_RESETBASE_OFS 0x0020 /* Reset Exception Base */
-#define GCMP_CCB_RESETBASE_BEV_SHF 12
-#define GCMP_CCB_RESETBASE_BEV_MSK GCMPCCBMSK(RESETBASE_BEV, 20)
-#define GCMP_CCB_ID_OFS 0x0028 /* Identification */
-#define GCMP_CCB_DINTGROUP_OFS 0x0030 /* DINT Group Participate */
-#define GCMP_CCB_DBGGROUP_OFS 0x0100 /* DebugBreak Group */
-
-extern int __init gcmp_probe(unsigned long, unsigned long);
-extern int __init gcmp_niocu(void);
-extern void __init gcmp_setregion(int, unsigned long, unsigned long, int);
-#endif /* _ASM_GCMPREGS_H */
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index b2e3e93dd7d..10f6a99f92c 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -11,6 +11,9 @@
#ifndef _ASM_GICREGS_H
#define _ASM_GICREGS_H
+#include <linux/bitmap.h>
+#include <linux/threads.h>
+
#undef GICISBYTELITTLEENDIAN
/* Constants */
@@ -377,6 +380,7 @@ extern unsigned int gic_compare_int (void);
extern cycle_t gic_read_count(void);
extern cycle_t gic_read_compare(void);
extern void gic_write_compare(cycle_t cnt);
+extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
extern void gic_send_ipi(unsigned int intr);
extern unsigned int plat_ipi_call_int_xlate(unsigned int);
extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h
index 0878701712f..4be1a57cdbb 100644
--- a/arch/mips/include/asm/gio_device.h
+++ b/arch/mips/include/asm/gio_device.h
@@ -50,7 +50,7 @@ static inline void gio_device_free(struct gio_device *dev)
extern int gio_register_driver(struct gio_driver *);
extern void gio_unregister_driver(struct gio_driver *);
-#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev)
-#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data))
+#define gio_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
+#define gio_set_drvdata(_dev, data) dev_set_drvdata(&(_dev)->dev, (data))
extern void gio_set_master(struct gio_device *);
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
index b0dd0c84df7..572e63ec2a3 100644
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -19,7 +19,6 @@
#ifdef __KERNEL__
-#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <asm/kmap_types.h>
diff --git a/arch/mips/include/asm/idle.h b/arch/mips/include/asm/idle.h
index d192158886b..d9f932de80e 100644
--- a/arch/mips/include/asm/idle.h
+++ b/arch/mips/include/asm/idle.h
@@ -1,6 +1,7 @@
#ifndef __ASM_IDLE_H
#define __ASM_IDLE_H
+#include <linux/cpuidle.h>
#include <linux/linkage.h>
extern void (*cpu_wait)(void);
@@ -20,4 +21,17 @@ static inline int address_is_in_r4k_wait_irqoff(unsigned long addr)
addr < (unsigned long)__pastwait;
}
+extern int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index);
+
+#define MIPS_CPUIDLE_WAIT_STATE {\
+ .enter = mips_cpuidle_wait_enter,\
+ .exit_latency = 1,\
+ .target_residency = 1,\
+ .power_usage = UINT_MAX,\
+ .flags = CPUIDLE_FLAG_TIME_VALID,\
+ .name = "wait",\
+ .desc = "MIPS wait",\
+}
+
#endif /* __ASM_IDLE_H */
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 3321dd5a887..933b50e125a 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -331,7 +331,7 @@ static inline void pfx##write##bwlq(type val, \
if (irq) \
local_irq_save(__flags); \
__asm__ __volatile__( \
- ".set mips3" "\t\t# __writeq""\n\t" \
+ ".set arch=r4000" "\t\t# __writeq""\n\t" \
"dsll32 %L0, %L0, 0" "\n\t" \
"dsrl32 %L0, %L0, 0" "\n\t" \
"dsll32 %M0, %M0, 0" "\n\t" \
@@ -361,7 +361,7 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \
if (irq) \
local_irq_save(__flags); \
__asm__ __volatile__( \
- ".set mips3" "\t\t# __readq" "\n\t" \
+ ".set arch=r4000" "\t\t# __readq" "\n\t" \
"ld %L0, %1" "\n\t" \
"dsra32 %M0, %L0, 0" "\n\t" \
"sll %L0, %L0, 0" "\n\t" \
@@ -584,7 +584,7 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int
*
* This API used to be exported; it now is for arch code internal use only.
*/
-#ifdef CONFIG_DMA_NONCOHERENT
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
extern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
extern void (*_dma_cache_wback)(unsigned long start, unsigned long size);
@@ -603,7 +603,7 @@ extern void (*_dma_cache_inv)(unsigned long start, unsigned long size);
#define dma_cache_inv(start,size) \
do { (void) (start); (void) (size); } while (0)
-#endif /* CONFIG_DMA_NONCOHERENT */
+#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
/*
* Read a 32-bit register that requires a 64-bit read cycle on the bus.
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 7bc2cdb3505..ae1f7b24dd1 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -26,104 +26,8 @@ static inline int irq_canonicalize(int irq)
#define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
-
-struct irqaction;
-
-extern unsigned long irq_hwmask[];
-extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
- unsigned long hwmask);
-
-static inline void smtc_im_ack_irq(unsigned int irq)
-{
- if (irq_hwmask[irq] & ST0_IM)
- set_c0_status(irq_hwmask[irq] & ST0_IM);
-}
-
-#else
-
-static inline void smtc_im_ack_irq(unsigned int irq)
-{
-}
-
-#endif /* CONFIG_MIPS_MT_SMTC */
-
-#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-#include <linux/cpumask.h>
-
-extern int plat_set_irq_affinity(struct irq_data *d,
- const struct cpumask *affinity, bool force);
-extern void smtc_forward_irq(struct irq_data *d);
-
-/*
- * IRQ affinity hook invoked at the beginning of interrupt dispatch
- * if option is enabled.
- *
- * Up through Linux 2.6.22 (at least) cpumask operations are very
- * inefficient on MIPS. Initial prototypes of SMTC IRQ affinity
- * used a "fast path" per-IRQ-descriptor cache of affinity information
- * to reduce latency. As there is a project afoot to optimize the
- * cpumask implementations, this version is optimistically assuming
- * that cpumask.h macro overhead is reasonable during interrupt dispatch.
- */
-static inline int handle_on_other_cpu(unsigned int irq)
-{
- struct irq_data *d = irq_get_irq_data(irq);
-
- if (cpumask_test_cpu(smp_processor_id(), d->affinity))
- return 0;
- smtc_forward_irq(d);
- return 1;
-}
-
-#else /* Not doing SMTC affinity */
-
-static inline int handle_on_other_cpu(unsigned int irq) { return 0; }
-
-#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
-
-#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
-
-static inline void smtc_im_backstop(unsigned int irq)
-{
- if (irq_hwmask[irq] & 0x0000ff00)
- write_c0_tccontext(read_c0_tccontext() &
- ~(irq_hwmask[irq] & 0x0000ff00));
-}
-
-/*
- * Clear interrupt mask handling "backstop" if irq_hwmask
- * entry so indicates. This implies that the ack() or end()
- * functions will take over re-enabling the low-level mask.
- * Otherwise it will be done on return from exception.
- */
-static inline int smtc_handle_on_other_cpu(unsigned int irq)
-{
- int ret = handle_on_other_cpu(irq);
-
- if (!ret)
- smtc_im_backstop(irq);
- return ret;
-}
-
-#else
-
-static inline void smtc_im_backstop(unsigned int irq) { }
-static inline int smtc_handle_on_other_cpu(unsigned int irq)
-{
- return handle_on_other_cpu(irq);
-}
-
-#endif
-
extern void do_IRQ(unsigned int irq);
-#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-
-extern void do_IRQ_no_affinity(unsigned int irq);
-
-#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
-
extern void arch_init_irq(void);
extern void spurious_interrupt(void);
diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
index 45c00951888..0fa5fdcd1f0 100644
--- a/arch/mips/include/asm/irqflags.h
+++ b/arch/mips/include/asm/irqflags.h
@@ -17,7 +17,7 @@
#include <linux/stringify.h>
#include <asm/hazards.h>
-#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
+#ifdef CONFIG_CPU_MIPSR2
static inline void arch_local_irq_disable(void)
{
@@ -118,30 +118,15 @@ void arch_local_irq_disable(void);
unsigned long arch_local_irq_save(void);
void arch_local_irq_restore(unsigned long flags);
void __arch_local_irq_restore(unsigned long flags);
-#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */
-
-
-extern void smtc_ipi_replay(void);
+#endif /* CONFIG_CPU_MIPSR2 */
static inline void arch_local_irq_enable(void)
{
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC kernel needs to do a software replay of queued
- * IPIs, at the cost of call overhead on each local_irq_enable()
- */
- smtc_ipi_replay();
-#endif
__asm__ __volatile__(
" .set push \n"
" .set reorder \n"
" .set noat \n"
-#ifdef CONFIG_MIPS_MT_SMTC
- " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n"
- " ori $1, 0x400 \n"
- " xori $1, 0x400 \n"
- " mtc0 $1, $2, 1 \n"
-#elif defined(CONFIG_CPU_MIPSR2)
+#if defined(CONFIG_CPU_MIPSR2)
" ei \n"
#else
" mfc0 $1,$12 \n"
@@ -163,11 +148,7 @@ static inline unsigned long arch_local_save_flags(void)
asm __volatile__(
" .set push \n"
" .set reorder \n"
-#ifdef CONFIG_MIPS_MT_SMTC
- " mfc0 %[flags], $2, 1 \n"
-#else
" mfc0 %[flags], $12 \n"
-#endif
" .set pop \n"
: [flags] "=r" (flags));
@@ -177,14 +158,7 @@ static inline unsigned long arch_local_save_flags(void)
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
- */
- return flags & 0x400;
-#else
return !(flags & 1);
-#endif
}
#endif /* #ifndef __ASSEMBLY__ */
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index 4d6d77ed9b9..e194f957ca8 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -22,7 +22,7 @@
static __always_inline bool arch_static_branch(struct static_key *key)
{
- asm goto("1:\tnop\n\t"
+ asm_volatile_goto("1:\tnop\n\t"
"nop\n\t"
".pushsection __jump_table, \"aw\"\n\t"
WORD_INSN " 1b, %l[l_yes], %0\n\t"
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 4d6fa0bf130..b0aa9556575 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -19,6 +19,38 @@
#include <linux/threads.h>
#include <linux/spinlock.h>
+/* MIPS KVM register ids */
+#define MIPS_CP0_32(_R, _S) \
+ (KVM_REG_MIPS | KVM_REG_SIZE_U32 | 0x10000 | (8 * (_R) + (_S)))
+
+#define MIPS_CP0_64(_R, _S) \
+ (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0x10000 | (8 * (_R) + (_S)))
+
+#define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO0 MIPS_CP0_64(2, 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO1 MIPS_CP0_64(3, 0)
+#define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0)
+#define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2)
+#define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0)
+#define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1)
+#define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0)
+#define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0)
+#define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0)
+#define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0)
+#define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0)
+#define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0)
+#define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0)
+#define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0)
+#define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0)
+#define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1)
+#define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0)
+#define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1)
+#define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2)
+#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3)
+#define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7)
+#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0)
+#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0)
+
#define KVM_MAX_VCPUS 1
#define KVM_USER_MEM_SLOTS 8
@@ -27,26 +59,19 @@
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
-/* Don't support huge pages */
-#define KVM_HPAGE_GFN_SHIFT(x) 0
-
-/* We don't currently support large pages. */
-#define KVM_NR_PAGE_SIZES 1
-#define KVM_PAGES_PER_HPAGE(x) 1
-
/* Special address that contains the comm page, used for reducing # of traps */
-#define KVM_GUEST_COMMPAGE_ADDR 0x0
+#define KVM_GUEST_COMMPAGE_ADDR 0x0
#define KVM_GUEST_KERNEL_MODE(vcpu) ((kvm_read_c0_guest_status(vcpu->arch.cop0) & (ST0_EXL | ST0_ERL)) || \
((kvm_read_c0_guest_status(vcpu->arch.cop0) & KSU_USER) == 0))
-#define KVM_GUEST_KUSEG 0x00000000UL
-#define KVM_GUEST_KSEG0 0x40000000UL
-#define KVM_GUEST_KSEG23 0x60000000UL
-#define KVM_GUEST_KSEGX(a) ((_ACAST32_(a)) & 0x60000000)
-#define KVM_GUEST_CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
+#define KVM_GUEST_KUSEG 0x00000000UL
+#define KVM_GUEST_KSEG0 0x40000000UL
+#define KVM_GUEST_KSEG23 0x60000000UL
+#define KVM_GUEST_KSEGX(a) ((_ACAST32_(a)) & 0x60000000)
+#define KVM_GUEST_CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
#define KVM_GUEST_CKSEG0ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0)
#define KVM_GUEST_CKSEG1ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG1)
@@ -59,17 +84,17 @@
#define KVM_GUEST_KSEG1ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG1)
#define KVM_GUEST_KSEG23ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG23)
-#define KVM_INVALID_PAGE 0xdeadbeef
-#define KVM_INVALID_INST 0xdeadbeef
-#define KVM_INVALID_ADDR 0xdeadbeef
+#define KVM_INVALID_PAGE 0xdeadbeef
+#define KVM_INVALID_INST 0xdeadbeef
+#define KVM_INVALID_ADDR 0xdeadbeef
-#define KVM_MALTA_GUEST_RTC_ADDR 0xb8000070UL
+#define KVM_MALTA_GUEST_RTC_ADDR 0xb8000070UL
-#define GUEST_TICKS_PER_JIFFY (40000000/HZ)
-#define MS_TO_NS(x) (x * 1E6L)
+#define GUEST_TICKS_PER_JIFFY (40000000/HZ)
+#define MS_TO_NS(x) (x * 1E6L)
-#define CAUSEB_DC 27
-#define CAUSEF_DC (_ULCAST_(1) << 27)
+#define CAUSEB_DC 27
+#define CAUSEF_DC (_ULCAST_(1) << 27)
struct kvm;
struct kvm_run;
@@ -133,8 +158,8 @@ struct kvm_arch {
int commpage_tlb;
};
-#define N_MIPS_COPROC_REGS 32
-#define N_MIPS_COPROC_SEL 8
+#define N_MIPS_COPROC_REGS 32
+#define N_MIPS_COPROC_SEL 8
struct mips_coproc {
unsigned long reg[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL];
@@ -146,124 +171,124 @@ struct mips_coproc {
/*
* Coprocessor 0 register names
*/
-#define MIPS_CP0_TLB_INDEX 0
-#define MIPS_CP0_TLB_RANDOM 1
-#define MIPS_CP0_TLB_LOW 2
-#define MIPS_CP0_TLB_LO0 2
-#define MIPS_CP0_TLB_LO1 3
-#define MIPS_CP0_TLB_CONTEXT 4
-#define MIPS_CP0_TLB_PG_MASK 5
-#define MIPS_CP0_TLB_WIRED 6
-#define MIPS_CP0_HWRENA 7
-#define MIPS_CP0_BAD_VADDR 8
-#define MIPS_CP0_COUNT 9
-#define MIPS_CP0_TLB_HI 10
-#define MIPS_CP0_COMPARE 11
-#define MIPS_CP0_STATUS 12
-#define MIPS_CP0_CAUSE 13
-#define MIPS_CP0_EXC_PC 14
-#define MIPS_CP0_PRID 15
-#define MIPS_CP0_CONFIG 16
-#define MIPS_CP0_LLADDR 17
-#define MIPS_CP0_WATCH_LO 18
-#define MIPS_CP0_WATCH_HI 19
-#define MIPS_CP0_TLB_XCONTEXT 20
-#define MIPS_CP0_ECC 26
-#define MIPS_CP0_CACHE_ERR 27
-#define MIPS_CP0_TAG_LO 28
-#define MIPS_CP0_TAG_HI 29
-#define MIPS_CP0_ERROR_PC 30
-#define MIPS_CP0_DEBUG 23
-#define MIPS_CP0_DEPC 24
-#define MIPS_CP0_PERFCNT 25
-#define MIPS_CP0_ERRCTL 26
-#define MIPS_CP0_DATA_LO 28
-#define MIPS_CP0_DATA_HI 29
-#define MIPS_CP0_DESAVE 31
-
-#define MIPS_CP0_CONFIG_SEL 0
-#define MIPS_CP0_CONFIG1_SEL 1
-#define MIPS_CP0_CONFIG2_SEL 2
-#define MIPS_CP0_CONFIG3_SEL 3
+#define MIPS_CP0_TLB_INDEX 0
+#define MIPS_CP0_TLB_RANDOM 1
+#define MIPS_CP0_TLB_LOW 2
+#define MIPS_CP0_TLB_LO0 2
+#define MIPS_CP0_TLB_LO1 3
+#define MIPS_CP0_TLB_CONTEXT 4
+#define MIPS_CP0_TLB_PG_MASK 5
+#define MIPS_CP0_TLB_WIRED 6
+#define MIPS_CP0_HWRENA 7
+#define MIPS_CP0_BAD_VADDR 8
+#define MIPS_CP0_COUNT 9
+#define MIPS_CP0_TLB_HI 10
+#define MIPS_CP0_COMPARE 11
+#define MIPS_CP0_STATUS 12
+#define MIPS_CP0_CAUSE 13
+#define MIPS_CP0_EXC_PC 14
+#define MIPS_CP0_PRID 15
+#define MIPS_CP0_CONFIG 16
+#define MIPS_CP0_LLADDR 17
+#define MIPS_CP0_WATCH_LO 18
+#define MIPS_CP0_WATCH_HI 19
+#define MIPS_CP0_TLB_XCONTEXT 20
+#define MIPS_CP0_ECC 26
+#define MIPS_CP0_CACHE_ERR 27
+#define MIPS_CP0_TAG_LO 28
+#define MIPS_CP0_TAG_HI 29
+#define MIPS_CP0_ERROR_PC 30
+#define MIPS_CP0_DEBUG 23
+#define MIPS_CP0_DEPC 24
+#define MIPS_CP0_PERFCNT 25
+#define MIPS_CP0_ERRCTL 26
+#define MIPS_CP0_DATA_LO 28
+#define MIPS_CP0_DATA_HI 29
+#define MIPS_CP0_DESAVE 31
+
+#define MIPS_CP0_CONFIG_SEL 0
+#define MIPS_CP0_CONFIG1_SEL 1
+#define MIPS_CP0_CONFIG2_SEL 2
+#define MIPS_CP0_CONFIG3_SEL 3
/* Config0 register bits */
-#define CP0C0_M 31
-#define CP0C0_K23 28
-#define CP0C0_KU 25
-#define CP0C0_MDU 20
-#define CP0C0_MM 17
-#define CP0C0_BM 16
-#define CP0C0_BE 15
-#define CP0C0_AT 13
-#define CP0C0_AR 10
-#define CP0C0_MT 7
-#define CP0C0_VI 3
-#define CP0C0_K0 0
+#define CP0C0_M 31
+#define CP0C0_K23 28
+#define CP0C0_KU 25
+#define CP0C0_MDU 20
+#define CP0C0_MM 17
+#define CP0C0_BM 16
+#define CP0C0_BE 15
+#define CP0C0_AT 13
+#define CP0C0_AR 10
+#define CP0C0_MT 7
+#define CP0C0_VI 3
+#define CP0C0_K0 0
/* Config1 register bits */
-#define CP0C1_M 31
-#define CP0C1_MMU 25
-#define CP0C1_IS 22
-#define CP0C1_IL 19
-#define CP0C1_IA 16
-#define CP0C1_DS 13
-#define CP0C1_DL 10
-#define CP0C1_DA 7
-#define CP0C1_C2 6
-#define CP0C1_MD 5
-#define CP0C1_PC 4
-#define CP0C1_WR 3
-#define CP0C1_CA 2
-#define CP0C1_EP 1
-#define CP0C1_FP 0
+#define CP0C1_M 31
+#define CP0C1_MMU 25
+#define CP0C1_IS 22
+#define CP0C1_IL 19
+#define CP0C1_IA 16
+#define CP0C1_DS 13
+#define CP0C1_DL 10
+#define CP0C1_DA 7
+#define CP0C1_C2 6
+#define CP0C1_MD 5
+#define CP0C1_PC 4
+#define CP0C1_WR 3
+#define CP0C1_CA 2
+#define CP0C1_EP 1
+#define CP0C1_FP 0
/* Config2 Register bits */
-#define CP0C2_M 31
-#define CP0C2_TU 28
-#define CP0C2_TS 24
-#define CP0C2_TL 20
-#define CP0C2_TA 16
-#define CP0C2_SU 12
-#define CP0C2_SS 8
-#define CP0C2_SL 4
-#define CP0C2_SA 0
+#define CP0C2_M 31
+#define CP0C2_TU 28
+#define CP0C2_TS 24
+#define CP0C2_TL 20
+#define CP0C2_TA 16
+#define CP0C2_SU 12
+#define CP0C2_SS 8
+#define CP0C2_SL 4
+#define CP0C2_SA 0
/* Config3 Register bits */
-#define CP0C3_M 31
-#define CP0C3_ISA_ON_EXC 16
-#define CP0C3_ULRI 13
-#define CP0C3_DSPP 10
-#define CP0C3_LPA 7
-#define CP0C3_VEIC 6
-#define CP0C3_VInt 5
-#define CP0C3_SP 4
-#define CP0C3_MT 2
-#define CP0C3_SM 1
-#define CP0C3_TL 0
+#define CP0C3_M 31
+#define CP0C3_ISA_ON_EXC 16
+#define CP0C3_ULRI 13
+#define CP0C3_DSPP 10
+#define CP0C3_LPA 7
+#define CP0C3_VEIC 6
+#define CP0C3_VInt 5
+#define CP0C3_SP 4
+#define CP0C3_MT 2
+#define CP0C3_SM 1
+#define CP0C3_TL 0
/* Have config1, Cacheable, noncoherent, write-back, write allocate*/
-#define MIPS_CONFIG0 \
+#define MIPS_CONFIG0 \
((1 << CP0C0_M) | (0x3 << CP0C0_K0))
/* Have config2, no coprocessor2 attached, no MDMX support attached,
no performance counters, watch registers present,
no code compression, EJTAG present, no FPU, no watch registers */
-#define MIPS_CONFIG1 \
-((1 << CP0C1_M) | \
- (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \
- (0 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \
+#define MIPS_CONFIG1 \
+((1 << CP0C1_M) | \
+ (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \
+ (0 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \
(0 << CP0C1_FP))
/* Have config3, no tertiary/secondary caches implemented */
-#define MIPS_CONFIG2 \
+#define MIPS_CONFIG2 \
((1 << CP0C2_M))
/* No config4, no DSP ASE, no large physaddr (PABITS),
no external interrupt controller, no vectored interrupts,
no 1kb pages, no SmartMIPS ASE, no trace logic */
-#define MIPS_CONFIG3 \
-((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
- (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
+#define MIPS_CONFIG3 \
+((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
+ (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
(0 << CP0C3_SM) | (0 << CP0C3_TL))
/* MMU types, the first four entries have the same layout as the
@@ -281,36 +306,36 @@ enum mips_mmu_types {
/*
* Trap codes
*/
-#define T_INT 0 /* Interrupt pending */
-#define T_TLB_MOD 1 /* TLB modified fault */
-#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */
-#define T_TLB_ST_MISS 3 /* TLB miss on a store */
-#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */
-#define T_ADDR_ERR_ST 5 /* Address error on a store */
-#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */
-#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */
-#define T_SYSCALL 8 /* System call */
-#define T_BREAK 9 /* Breakpoint */
-#define T_RES_INST 10 /* Reserved instruction exception */
-#define T_COP_UNUSABLE 11 /* Coprocessor unusable */
-#define T_OVFLOW 12 /* Arithmetic overflow */
+#define T_INT 0 /* Interrupt pending */
+#define T_TLB_MOD 1 /* TLB modified fault */
+#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */
+#define T_TLB_ST_MISS 3 /* TLB miss on a store */
+#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */
+#define T_ADDR_ERR_ST 5 /* Address error on a store */
+#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */
+#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */
+#define T_SYSCALL 8 /* System call */
+#define T_BREAK 9 /* Breakpoint */
+#define T_RES_INST 10 /* Reserved instruction exception */
+#define T_COP_UNUSABLE 11 /* Coprocessor unusable */
+#define T_OVFLOW 12 /* Arithmetic overflow */
/*
* Trap definitions added for r4000 port.
*/
-#define T_TRAP 13 /* Trap instruction */
-#define T_VCEI 14 /* Virtual coherency exception */
-#define T_FPE 15 /* Floating point exception */
-#define T_WATCH 23 /* Watch address reference */
-#define T_VCED 31 /* Virtual coherency data */
+#define T_TRAP 13 /* Trap instruction */
+#define T_VCEI 14 /* Virtual coherency exception */
+#define T_FPE 15 /* Floating point exception */
+#define T_WATCH 23 /* Watch address reference */
+#define T_VCED 31 /* Virtual coherency data */
/* Resume Flags */
-#define RESUME_FLAG_DR (1<<0) /* Reload guest nonvolatile state? */
-#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
+#define RESUME_FLAG_DR (1<<0) /* Reload guest nonvolatile state? */
+#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
-#define RESUME_GUEST 0
-#define RESUME_GUEST_DR RESUME_FLAG_DR
-#define RESUME_HOST RESUME_FLAG_HOST
+#define RESUME_GUEST 0
+#define RESUME_GUEST_DR RESUME_FLAG_DR
+#define RESUME_HOST RESUME_FLAG_HOST
enum emulation_result {
EMULATE_DONE, /* no further processing */
@@ -320,24 +345,27 @@ enum emulation_result {
EMULATE_PRIV_FAIL,
};
-#define MIPS3_PG_G 0x00000001 /* Global; ignore ASID if in lo0 & lo1 */
-#define MIPS3_PG_V 0x00000002 /* Valid */
-#define MIPS3_PG_NV 0x00000000
-#define MIPS3_PG_D 0x00000004 /* Dirty */
+#define MIPS3_PG_G 0x00000001 /* Global; ignore ASID if in lo0 & lo1 */
+#define MIPS3_PG_V 0x00000002 /* Valid */
+#define MIPS3_PG_NV 0x00000000
+#define MIPS3_PG_D 0x00000004 /* Dirty */
#define mips3_paddr_to_tlbpfn(x) \
- (((unsigned long)(x) >> MIPS3_PG_SHIFT) & MIPS3_PG_FRAME)
+ (((unsigned long)(x) >> MIPS3_PG_SHIFT) & MIPS3_PG_FRAME)
#define mips3_tlbpfn_to_paddr(x) \
- ((unsigned long)((x) & MIPS3_PG_FRAME) << MIPS3_PG_SHIFT)
+ ((unsigned long)((x) & MIPS3_PG_FRAME) << MIPS3_PG_SHIFT)
-#define MIPS3_PG_SHIFT 6
-#define MIPS3_PG_FRAME 0x3fffffc0
+#define MIPS3_PG_SHIFT 6
+#define MIPS3_PG_FRAME 0x3fffffc0
-#define VPN2_MASK 0xffffe000
-#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && ((x).tlb_lo1 & MIPS3_PG_G))
-#define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK)
-#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK)
-#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) ? ((x).tlb_lo1 & MIPS3_PG_V) : ((x).tlb_lo0 & MIPS3_PG_V))
+#define VPN2_MASK 0xffffe000
+#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && \
+ ((x).tlb_lo1 & MIPS3_PG_G))
+#define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK)
+#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK)
+#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) \
+ ? ((x).tlb_lo1 & MIPS3_PG_V) \
+ : ((x).tlb_lo0 & MIPS3_PG_V))
struct kvm_mips_tlb {
long tlb_mask;
@@ -346,7 +374,7 @@ struct kvm_mips_tlb {
long tlb_lo1;
};
-#define KVM_MIPS_GUEST_TLB_SIZE 64
+#define KVM_MIPS_GUEST_TLB_SIZE 64
struct kvm_vcpu_arch {
void *host_ebase, *guest_ebase;
unsigned long host_stack;
@@ -376,8 +404,19 @@ struct kvm_vcpu_arch {
u32 io_gpr; /* GPR used as IO source/target */
- /* Used to calibrate the virutal count register for the guest */
- int32_t host_cp0_count;
+ struct hrtimer comparecount_timer;
+ /* Count timer control KVM register */
+ uint32_t count_ctl;
+ /* Count bias from the raw time */
+ uint32_t count_bias;
+ /* Frequency of timer in Hz */
+ uint32_t count_hz;
+ /* Dynamic nanosecond bias (multiple of count_period) to avoid overflow */
+ s64 count_dyn_bias;
+ /* Resume time */
+ ktime_t count_resume;
+ /* Period of timer tick in ns */
+ u64 count_period;
/* Bitmask of exceptions that are pending */
unsigned long pending_exceptions;
@@ -398,11 +437,6 @@ struct kvm_vcpu_arch {
uint32_t guest_kernel_asid[NR_CPUS];
struct mm_struct guest_kernel_mm, guest_user_mm;
- struct kvm_mips_tlb shadow_tlb[NR_CPUS][KVM_MIPS_GUEST_TLB_SIZE];
-
-
- struct hrtimer comparecount_timer;
-
int last_sched_cpu;
/* WAIT executed */
@@ -410,92 +444,158 @@ struct kvm_vcpu_arch {
};
-#define kvm_read_c0_guest_index(cop0) (cop0->reg[MIPS_CP0_TLB_INDEX][0])
-#define kvm_write_c0_guest_index(cop0, val) (cop0->reg[MIPS_CP0_TLB_INDEX][0] = val)
-#define kvm_read_c0_guest_entrylo0(cop0) (cop0->reg[MIPS_CP0_TLB_LO0][0])
-#define kvm_read_c0_guest_entrylo1(cop0) (cop0->reg[MIPS_CP0_TLB_LO1][0])
-#define kvm_read_c0_guest_context(cop0) (cop0->reg[MIPS_CP0_TLB_CONTEXT][0])
-#define kvm_write_c0_guest_context(cop0, val) (cop0->reg[MIPS_CP0_TLB_CONTEXT][0] = (val))
-#define kvm_read_c0_guest_userlocal(cop0) (cop0->reg[MIPS_CP0_TLB_CONTEXT][2])
-#define kvm_read_c0_guest_pagemask(cop0) (cop0->reg[MIPS_CP0_TLB_PG_MASK][0])
-#define kvm_write_c0_guest_pagemask(cop0, val) (cop0->reg[MIPS_CP0_TLB_PG_MASK][0] = (val))
-#define kvm_read_c0_guest_wired(cop0) (cop0->reg[MIPS_CP0_TLB_WIRED][0])
-#define kvm_write_c0_guest_wired(cop0, val) (cop0->reg[MIPS_CP0_TLB_WIRED][0] = (val))
-#define kvm_read_c0_guest_badvaddr(cop0) (cop0->reg[MIPS_CP0_BAD_VADDR][0])
-#define kvm_write_c0_guest_badvaddr(cop0, val) (cop0->reg[MIPS_CP0_BAD_VADDR][0] = (val))
-#define kvm_read_c0_guest_count(cop0) (cop0->reg[MIPS_CP0_COUNT][0])
-#define kvm_write_c0_guest_count(cop0, val) (cop0->reg[MIPS_CP0_COUNT][0] = (val))
-#define kvm_read_c0_guest_entryhi(cop0) (cop0->reg[MIPS_CP0_TLB_HI][0])
-#define kvm_write_c0_guest_entryhi(cop0, val) (cop0->reg[MIPS_CP0_TLB_HI][0] = (val))
-#define kvm_read_c0_guest_compare(cop0) (cop0->reg[MIPS_CP0_COMPARE][0])
-#define kvm_write_c0_guest_compare(cop0, val) (cop0->reg[MIPS_CP0_COMPARE][0] = (val))
-#define kvm_read_c0_guest_status(cop0) (cop0->reg[MIPS_CP0_STATUS][0])
-#define kvm_write_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] = (val))
-#define kvm_read_c0_guest_intctl(cop0) (cop0->reg[MIPS_CP0_STATUS][1])
-#define kvm_write_c0_guest_intctl(cop0, val) (cop0->reg[MIPS_CP0_STATUS][1] = (val))
-#define kvm_read_c0_guest_cause(cop0) (cop0->reg[MIPS_CP0_CAUSE][0])
-#define kvm_write_c0_guest_cause(cop0, val) (cop0->reg[MIPS_CP0_CAUSE][0] = (val))
-#define kvm_read_c0_guest_epc(cop0) (cop0->reg[MIPS_CP0_EXC_PC][0])
-#define kvm_write_c0_guest_epc(cop0, val) (cop0->reg[MIPS_CP0_EXC_PC][0] = (val))
-#define kvm_read_c0_guest_prid(cop0) (cop0->reg[MIPS_CP0_PRID][0])
-#define kvm_write_c0_guest_prid(cop0, val) (cop0->reg[MIPS_CP0_PRID][0] = (val))
-#define kvm_read_c0_guest_ebase(cop0) (cop0->reg[MIPS_CP0_PRID][1])
-#define kvm_write_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] = (val))
-#define kvm_read_c0_guest_config(cop0) (cop0->reg[MIPS_CP0_CONFIG][0])
-#define kvm_read_c0_guest_config1(cop0) (cop0->reg[MIPS_CP0_CONFIG][1])
-#define kvm_read_c0_guest_config2(cop0) (cop0->reg[MIPS_CP0_CONFIG][2])
-#define kvm_read_c0_guest_config3(cop0) (cop0->reg[MIPS_CP0_CONFIG][3])
-#define kvm_read_c0_guest_config7(cop0) (cop0->reg[MIPS_CP0_CONFIG][7])
-#define kvm_write_c0_guest_config(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][0] = (val))
-#define kvm_write_c0_guest_config1(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][1] = (val))
-#define kvm_write_c0_guest_config2(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][2] = (val))
-#define kvm_write_c0_guest_config3(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][3] = (val))
-#define kvm_write_c0_guest_config7(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][7] = (val))
-#define kvm_read_c0_guest_errorepc(cop0) (cop0->reg[MIPS_CP0_ERROR_PC][0])
-#define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val))
-
-#define kvm_set_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] |= (val))
-#define kvm_clear_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] &= ~(val))
-#define kvm_set_c0_guest_cause(cop0, val) (cop0->reg[MIPS_CP0_CAUSE][0] |= (val))
-#define kvm_clear_c0_guest_cause(cop0, val) (cop0->reg[MIPS_CP0_CAUSE][0] &= ~(val))
-#define kvm_change_c0_guest_cause(cop0, change, val) \
-{ \
- kvm_clear_c0_guest_cause(cop0, change); \
- kvm_set_c0_guest_cause(cop0, ((val) & (change))); \
+#define kvm_read_c0_guest_index(cop0) (cop0->reg[MIPS_CP0_TLB_INDEX][0])
+#define kvm_write_c0_guest_index(cop0, val) (cop0->reg[MIPS_CP0_TLB_INDEX][0] = val)
+#define kvm_read_c0_guest_entrylo0(cop0) (cop0->reg[MIPS_CP0_TLB_LO0][0])
+#define kvm_read_c0_guest_entrylo1(cop0) (cop0->reg[MIPS_CP0_TLB_LO1][0])
+#define kvm_read_c0_guest_context(cop0) (cop0->reg[MIPS_CP0_TLB_CONTEXT][0])
+#define kvm_write_c0_guest_context(cop0, val) (cop0->reg[MIPS_CP0_TLB_CONTEXT][0] = (val))
+#define kvm_read_c0_guest_userlocal(cop0) (cop0->reg[MIPS_CP0_TLB_CONTEXT][2])
+#define kvm_write_c0_guest_userlocal(cop0, val) (cop0->reg[MIPS_CP0_TLB_CONTEXT][2] = (val))
+#define kvm_read_c0_guest_pagemask(cop0) (cop0->reg[MIPS_CP0_TLB_PG_MASK][0])
+#define kvm_write_c0_guest_pagemask(cop0, val) (cop0->reg[MIPS_CP0_TLB_PG_MASK][0] = (val))
+#define kvm_read_c0_guest_wired(cop0) (cop0->reg[MIPS_CP0_TLB_WIRED][0])
+#define kvm_write_c0_guest_wired(cop0, val) (cop0->reg[MIPS_CP0_TLB_WIRED][0] = (val))
+#define kvm_read_c0_guest_hwrena(cop0) (cop0->reg[MIPS_CP0_HWRENA][0])
+#define kvm_write_c0_guest_hwrena(cop0, val) (cop0->reg[MIPS_CP0_HWRENA][0] = (val))
+#define kvm_read_c0_guest_badvaddr(cop0) (cop0->reg[MIPS_CP0_BAD_VADDR][0])
+#define kvm_write_c0_guest_badvaddr(cop0, val) (cop0->reg[MIPS_CP0_BAD_VADDR][0] = (val))
+#define kvm_read_c0_guest_count(cop0) (cop0->reg[MIPS_CP0_COUNT][0])
+#define kvm_write_c0_guest_count(cop0, val) (cop0->reg[MIPS_CP0_COUNT][0] = (val))
+#define kvm_read_c0_guest_entryhi(cop0) (cop0->reg[MIPS_CP0_TLB_HI][0])
+#define kvm_write_c0_guest_entryhi(cop0, val) (cop0->reg[MIPS_CP0_TLB_HI][0] = (val))
+#define kvm_read_c0_guest_compare(cop0) (cop0->reg[MIPS_CP0_COMPARE][0])
+#define kvm_write_c0_guest_compare(cop0, val) (cop0->reg[MIPS_CP0_COMPARE][0] = (val))
+#define kvm_read_c0_guest_status(cop0) (cop0->reg[MIPS_CP0_STATUS][0])
+#define kvm_write_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] = (val))
+#define kvm_read_c0_guest_intctl(cop0) (cop0->reg[MIPS_CP0_STATUS][1])
+#define kvm_write_c0_guest_intctl(cop0, val) (cop0->reg[MIPS_CP0_STATUS][1] = (val))
+#define kvm_read_c0_guest_cause(cop0) (cop0->reg[MIPS_CP0_CAUSE][0])
+#define kvm_write_c0_guest_cause(cop0, val) (cop0->reg[MIPS_CP0_CAUSE][0] = (val))
+#define kvm_read_c0_guest_epc(cop0) (cop0->reg[MIPS_CP0_EXC_PC][0])
+#define kvm_write_c0_guest_epc(cop0, val) (cop0->reg[MIPS_CP0_EXC_PC][0] = (val))
+#define kvm_read_c0_guest_prid(cop0) (cop0->reg[MIPS_CP0_PRID][0])
+#define kvm_write_c0_guest_prid(cop0, val) (cop0->reg[MIPS_CP0_PRID][0] = (val))
+#define kvm_read_c0_guest_ebase(cop0) (cop0->reg[MIPS_CP0_PRID][1])
+#define kvm_write_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] = (val))
+#define kvm_read_c0_guest_config(cop0) (cop0->reg[MIPS_CP0_CONFIG][0])
+#define kvm_read_c0_guest_config1(cop0) (cop0->reg[MIPS_CP0_CONFIG][1])
+#define kvm_read_c0_guest_config2(cop0) (cop0->reg[MIPS_CP0_CONFIG][2])
+#define kvm_read_c0_guest_config3(cop0) (cop0->reg[MIPS_CP0_CONFIG][3])
+#define kvm_read_c0_guest_config7(cop0) (cop0->reg[MIPS_CP0_CONFIG][7])
+#define kvm_write_c0_guest_config(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][0] = (val))
+#define kvm_write_c0_guest_config1(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][1] = (val))
+#define kvm_write_c0_guest_config2(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][2] = (val))
+#define kvm_write_c0_guest_config3(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][3] = (val))
+#define kvm_write_c0_guest_config7(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][7] = (val))
+#define kvm_read_c0_guest_errorepc(cop0) (cop0->reg[MIPS_CP0_ERROR_PC][0])
+#define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val))
+
+/*
+ * Some of the guest registers may be modified asynchronously (e.g. from a
+ * hrtimer callback in hard irq context) and therefore need stronger atomicity
+ * guarantees than other registers.
+ */
+
+static inline void _kvm_atomic_set_c0_guest_reg(unsigned long *reg,
+ unsigned long val)
+{
+ unsigned long temp;
+ do {
+ __asm__ __volatile__(
+ " .set mips3 \n"
+ " " __LL "%0, %1 \n"
+ " or %0, %2 \n"
+ " " __SC "%0, %1 \n"
+ " .set mips0 \n"
+ : "=&r" (temp), "+m" (*reg)
+ : "r" (val));
+ } while (unlikely(!temp));
+}
+
+static inline void _kvm_atomic_clear_c0_guest_reg(unsigned long *reg,
+ unsigned long val)
+{
+ unsigned long temp;
+ do {
+ __asm__ __volatile__(
+ " .set mips3 \n"
+ " " __LL "%0, %1 \n"
+ " and %0, %2 \n"
+ " " __SC "%0, %1 \n"
+ " .set mips0 \n"
+ : "=&r" (temp), "+m" (*reg)
+ : "r" (~val));
+ } while (unlikely(!temp));
+}
+
+static inline void _kvm_atomic_change_c0_guest_reg(unsigned long *reg,
+ unsigned long change,
+ unsigned long val)
+{
+ unsigned long temp;
+ do {
+ __asm__ __volatile__(
+ " .set mips3 \n"
+ " " __LL "%0, %1 \n"
+ " and %0, %2 \n"
+ " or %0, %3 \n"
+ " " __SC "%0, %1 \n"
+ " .set mips0 \n"
+ : "=&r" (temp), "+m" (*reg)
+ : "r" (~change), "r" (val & change));
+ } while (unlikely(!temp));
}
-#define kvm_set_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] |= (val))
-#define kvm_clear_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] &= ~(val))
-#define kvm_change_c0_guest_ebase(cop0, change, val) \
-{ \
- kvm_clear_c0_guest_ebase(cop0, change); \
- kvm_set_c0_guest_ebase(cop0, ((val) & (change))); \
+
+#define kvm_set_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] |= (val))
+#define kvm_clear_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] &= ~(val))
+
+/* Cause can be modified asynchronously from hardirq hrtimer callback */
+#define kvm_set_c0_guest_cause(cop0, val) \
+ _kvm_atomic_set_c0_guest_reg(&cop0->reg[MIPS_CP0_CAUSE][0], val)
+#define kvm_clear_c0_guest_cause(cop0, val) \
+ _kvm_atomic_clear_c0_guest_reg(&cop0->reg[MIPS_CP0_CAUSE][0], val)
+#define kvm_change_c0_guest_cause(cop0, change, val) \
+ _kvm_atomic_change_c0_guest_reg(&cop0->reg[MIPS_CP0_CAUSE][0], \
+ change, val)
+
+#define kvm_set_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] |= (val))
+#define kvm_clear_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] &= ~(val))
+#define kvm_change_c0_guest_ebase(cop0, change, val) \
+{ \
+ kvm_clear_c0_guest_ebase(cop0, change); \
+ kvm_set_c0_guest_ebase(cop0, ((val) & (change))); \
}
struct kvm_mips_callbacks {
- int (*handle_cop_unusable) (struct kvm_vcpu *vcpu);
- int (*handle_tlb_mod) (struct kvm_vcpu *vcpu);
- int (*handle_tlb_ld_miss) (struct kvm_vcpu *vcpu);
- int (*handle_tlb_st_miss) (struct kvm_vcpu *vcpu);
- int (*handle_addr_err_st) (struct kvm_vcpu *vcpu);
- int (*handle_addr_err_ld) (struct kvm_vcpu *vcpu);
- int (*handle_syscall) (struct kvm_vcpu *vcpu);
- int (*handle_res_inst) (struct kvm_vcpu *vcpu);
- int (*handle_break) (struct kvm_vcpu *vcpu);
- int (*vm_init) (struct kvm *kvm);
- int (*vcpu_init) (struct kvm_vcpu *vcpu);
- int (*vcpu_setup) (struct kvm_vcpu *vcpu);
- gpa_t(*gva_to_gpa) (gva_t gva);
- void (*queue_timer_int) (struct kvm_vcpu *vcpu);
- void (*dequeue_timer_int) (struct kvm_vcpu *vcpu);
- void (*queue_io_int) (struct kvm_vcpu *vcpu,
- struct kvm_mips_interrupt *irq);
- void (*dequeue_io_int) (struct kvm_vcpu *vcpu,
- struct kvm_mips_interrupt *irq);
- int (*irq_deliver) (struct kvm_vcpu *vcpu, unsigned int priority,
- uint32_t cause);
- int (*irq_clear) (struct kvm_vcpu *vcpu, unsigned int priority,
- uint32_t cause);
+ int (*handle_cop_unusable)(struct kvm_vcpu *vcpu);
+ int (*handle_tlb_mod)(struct kvm_vcpu *vcpu);
+ int (*handle_tlb_ld_miss)(struct kvm_vcpu *vcpu);
+ int (*handle_tlb_st_miss)(struct kvm_vcpu *vcpu);
+ int (*handle_addr_err_st)(struct kvm_vcpu *vcpu);
+ int (*handle_addr_err_ld)(struct kvm_vcpu *vcpu);
+ int (*handle_syscall)(struct kvm_vcpu *vcpu);
+ int (*handle_res_inst)(struct kvm_vcpu *vcpu);
+ int (*handle_break)(struct kvm_vcpu *vcpu);
+ int (*vm_init)(struct kvm *kvm);
+ int (*vcpu_init)(struct kvm_vcpu *vcpu);
+ int (*vcpu_setup)(struct kvm_vcpu *vcpu);
+ gpa_t (*gva_to_gpa)(gva_t gva);
+ void (*queue_timer_int)(struct kvm_vcpu *vcpu);
+ void (*dequeue_timer_int)(struct kvm_vcpu *vcpu);
+ void (*queue_io_int)(struct kvm_vcpu *vcpu,
+ struct kvm_mips_interrupt *irq);
+ void (*dequeue_io_int)(struct kvm_vcpu *vcpu,
+ struct kvm_mips_interrupt *irq);
+ int (*irq_deliver)(struct kvm_vcpu *vcpu, unsigned int priority,
+ uint32_t cause);
+ int (*irq_clear)(struct kvm_vcpu *vcpu, unsigned int priority,
+ uint32_t cause);
+ int (*get_one_reg)(struct kvm_vcpu *vcpu,
+ const struct kvm_one_reg *reg, s64 *v);
+ int (*set_one_reg)(struct kvm_vcpu *vcpu,
+ const struct kvm_one_reg *reg, s64 v);
};
extern struct kvm_mips_callbacks *kvm_mips_callbacks;
int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks);
@@ -536,7 +636,6 @@ extern enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause,
extern void kvm_mips_dump_host_tlbs(void);
extern void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu);
-extern void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu);
extern void kvm_mips_flush_host_tlb(int skip_kseg0);
extern int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long entryhi);
extern int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index);
@@ -548,10 +647,7 @@ extern unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu
unsigned long gva);
extern void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
struct kvm_vcpu *vcpu);
-extern void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu);
-extern void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu);
extern void kvm_local_flush_tlb_all(void);
-extern void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu);
extern void kvm_mips_alloc_new_mmu_context(struct kvm_vcpu *vcpu);
extern void kvm_mips_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
extern void kvm_mips_vcpu_put(struct kvm_vcpu *vcpu);
@@ -618,7 +714,16 @@ extern enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
struct kvm_run *run);
-enum emulation_result kvm_mips_emulate_count(struct kvm_vcpu *vcpu);
+uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu);
+void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count);
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare);
+void kvm_mips_init_count(struct kvm_vcpu *vcpu);
+int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl);
+int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume);
+int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz);
+void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu);
+void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu);
+enum hrtimer_restart kvm_mips_count_timeout(struct kvm_vcpu *vcpu);
enum emulation_result kvm_mips_check_privilege(unsigned long cause,
uint32_t *opc,
@@ -655,7 +760,6 @@ extern int kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc,
struct kvm_vcpu *vcpu);
/* Misc */
-extern void mips32_SyncICache(unsigned long addr, unsigned long size);
extern int kvm_mips_dump_stats(struct kvm_vcpu *vcpu);
extern unsigned long kvm_mips_get_ramsize(struct kvm *kvm);
diff --git a/arch/mips/include/asm/kvm_para.h b/arch/mips/include/asm/kvm_para.h
new file mode 100644
index 00000000000..5a9aa918abe
--- /dev/null
+++ b/arch/mips/include/asm/kvm_para.h
@@ -0,0 +1,109 @@
+#ifndef _ASM_MIPS_KVM_PARA_H
+#define _ASM_MIPS_KVM_PARA_H
+
+#include <uapi/asm/kvm_para.h>
+
+#define KVM_HYPERCALL ".word 0x42000028"
+
+/*
+ * Hypercalls for KVM.
+ *
+ * Hypercall number is passed in v0.
+ * Return value will be placed in v0.
+ * Up to 3 arguments are passed in a0, a1, and a2.
+ */
+static inline unsigned long kvm_hypercall0(unsigned long num)
+{
+ register unsigned long n asm("v0");
+ register unsigned long r asm("v0");
+
+ n = num;
+ __asm__ __volatile__(
+ KVM_HYPERCALL
+ : "=r" (r) : "r" (n) : "memory"
+ );
+
+ return r;
+}
+
+static inline unsigned long kvm_hypercall1(unsigned long num,
+ unsigned long arg0)
+{
+ register unsigned long n asm("v0");
+ register unsigned long r asm("v0");
+ register unsigned long a0 asm("a0");
+
+ n = num;
+ a0 = arg0;
+ __asm__ __volatile__(
+ KVM_HYPERCALL
+ : "=r" (r) : "r" (n), "r" (a0) : "memory"
+ );
+
+ return r;
+}
+
+static inline unsigned long kvm_hypercall2(unsigned long num,
+ unsigned long arg0, unsigned long arg1)
+{
+ register unsigned long n asm("v0");
+ register unsigned long r asm("v0");
+ register unsigned long a0 asm("a0");
+ register unsigned long a1 asm("a1");
+
+ n = num;
+ a0 = arg0;
+ a1 = arg1;
+ __asm__ __volatile__(
+ KVM_HYPERCALL
+ : "=r" (r) : "r" (n), "r" (a0), "r" (a1) : "memory"
+ );
+
+ return r;
+}
+
+static inline unsigned long kvm_hypercall3(unsigned long num,
+ unsigned long arg0, unsigned long arg1, unsigned long arg2)
+{
+ register unsigned long n asm("v0");
+ register unsigned long r asm("v0");
+ register unsigned long a0 asm("a0");
+ register unsigned long a1 asm("a1");
+ register unsigned long a2 asm("a2");
+
+ n = num;
+ a0 = arg0;
+ a1 = arg1;
+ a2 = arg2;
+ __asm__ __volatile__(
+ KVM_HYPERCALL
+ : "=r" (r) : "r" (n), "r" (a0), "r" (a1), "r" (a2) : "memory"
+ );
+
+ return r;
+}
+
+static inline bool kvm_check_and_clear_guest_paused(void)
+{
+ return false;
+}
+
+static inline unsigned int kvm_arch_para_features(void)
+{
+ return 0;
+}
+
+#ifdef CONFIG_MIPS_PARAVIRT
+static inline bool kvm_para_available(void)
+{
+ return true;
+}
+#else
+static inline bool kvm_para_available(void)
+{
+ return false;
+}
+#endif
+
+
+#endif /* _ASM_MIPS_KVM_PARA_H */
diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index d44622cd74b..46dfc3c1fd4 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -33,7 +33,7 @@ static __inline__ long local_add_return(long i, local_t * l)
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1:" __LL "%1, %2 # local_add_return \n"
" addu %0, %1, %3 \n"
__SC "%0, %2 \n"
@@ -47,7 +47,7 @@ static __inline__ long local_add_return(long i, local_t * l)
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1:" __LL "%1, %2 # local_add_return \n"
" addu %0, %1, %3 \n"
__SC "%0, %2 \n"
@@ -78,7 +78,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1:" __LL "%1, %2 # local_sub_return \n"
" subu %0, %1, %3 \n"
__SC "%0, %2 \n"
@@ -92,7 +92,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
unsigned long temp;
__asm__ __volatile__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1:" __LL "%1, %2 # local_sub_return \n"
" subu %0, %1, %3 \n"
__SC "%0, %2 \n"
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index b86a1253a5b..cd41e93bc1d 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -16,7 +16,6 @@
#define __ASM_MACH_AR71XX_REGS_H
#include <linux/types.h>
-#include <linux/init.h>
#include <linux/io.h>
#include <linux/bitops.h>
diff --git a/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h b/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h
deleted file mode 100644
index 6cb30f2b719..00000000000
--- a/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Platform data definition for Atheros AR933X UART
- *
- * Copyright (C) 2011 Gabor Juhos <juhosg@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 _AR933X_UART_PLATFORM_H
-#define _AR933X_UART_PLATFORM_H
-
-struct ar933x_uart_platform_data {
- unsigned uartclk;
-};
-
-#endif /* _AR933X_UART_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h
index 3e11a468cdf..b4c3ecb17d4 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000.h
@@ -43,6 +43,8 @@
#include <linux/io.h>
#include <linux/irq.h>
+#include <asm/cpu.h>
+
/* cpu pipeline flush */
void static inline au_sync(void)
{
@@ -140,7 +142,7 @@ static inline int au1xxx_cpu_needs_config_od(void)
static inline int alchemy_get_cputype(void)
{
- switch (read_c0_prid() & 0xffff0000) {
+ switch (read_c0_prid() & (PRID_OPT_MASK | PRID_COMP_MASK)) {
case 0x00030000:
return ALCHEMY_CPU_AU1000;
break;
@@ -1159,18 +1161,6 @@ enum soc_au1200_ints {
#define MAC_RX_BUFF3_STATUS 0x30
#define MAC_RX_BUFF3_ADDR 0x34
-#define UART_RX 0 /* Receive buffer */
-#define UART_TX 4 /* Transmit buffer */
-#define UART_IER 8 /* Interrupt Enable Register */
-#define UART_IIR 0xC /* Interrupt ID Register */
-#define UART_FCR 0x10 /* FIFO Control Register */
-#define UART_LCR 0x14 /* Line Control Register */
-#define UART_MCR 0x18 /* Modem Control Register */
-#define UART_LSR 0x1C /* Line Status Register */
-#define UART_MSR 0x20 /* Modem Status Register */
-#define UART_CLK 0x28 /* Baud Rate Clock Divider */
-#define UART_MOD_CNTRL 0x100 /* Module Control */
-
/* SSIO */
#define SSI0_STATUS 0xB1600000
# define SSI_STATUS_BF (1 << 4)
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
index cc7563ba1cb..7527c1d33d0 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -56,4 +56,6 @@ void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
const char *prefix);
#endif
+void bcm47xx_set_system_type(u16 chip_id);
+
#endif /* __ASM_BCM47XX_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
new file mode 100644
index 00000000000..bba7399a49a
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -0,0 +1,117 @@
+#ifndef __BCM47XX_BOARD_H
+#define __BCM47XX_BOARD_H
+
+enum bcm47xx_board {
+ BCM47XX_BOARD_ASUS_RTAC66U,
+ BCM47XX_BOARD_ASUS_RTN10,
+ BCM47XX_BOARD_ASUS_RTN10D,
+ BCM47XX_BOARD_ASUS_RTN10U,
+ BCM47XX_BOARD_ASUS_RTN12,
+ BCM47XX_BOARD_ASUS_RTN12B1,
+ BCM47XX_BOARD_ASUS_RTN12C1,
+ BCM47XX_BOARD_ASUS_RTN12D1,
+ BCM47XX_BOARD_ASUS_RTN12HP,
+ BCM47XX_BOARD_ASUS_RTN15U,
+ BCM47XX_BOARD_ASUS_RTN16,
+ BCM47XX_BOARD_ASUS_RTN53,
+ BCM47XX_BOARD_ASUS_RTN66U,
+ BCM47XX_BOARD_ASUS_WL300G,
+ BCM47XX_BOARD_ASUS_WL320GE,
+ BCM47XX_BOARD_ASUS_WL330GE,
+ BCM47XX_BOARD_ASUS_WL500GD,
+ BCM47XX_BOARD_ASUS_WL500GPV1,
+ BCM47XX_BOARD_ASUS_WL500GPV2,
+ BCM47XX_BOARD_ASUS_WL500W,
+ BCM47XX_BOARD_ASUS_WL520GC,
+ BCM47XX_BOARD_ASUS_WL520GU,
+ BCM47XX_BOARD_ASUS_WL700GE,
+ BCM47XX_BOARD_ASUS_WLHDD,
+
+ BCM47XX_BOARD_BELKIN_F7D3301,
+ BCM47XX_BOARD_BELKIN_F7D3302,
+ BCM47XX_BOARD_BELKIN_F7D4301,
+ BCM47XX_BOARD_BELKIN_F7D4302,
+ BCM47XX_BOARD_BELKIN_F7D4401,
+
+ BCM47XX_BOARD_BUFFALO_WBR2_G54,
+ BCM47XX_BOARD_BUFFALO_WHR2_A54G54,
+ BCM47XX_BOARD_BUFFALO_WHR_G125,
+ BCM47XX_BOARD_BUFFALO_WHR_G54S,
+ BCM47XX_BOARD_BUFFALO_WHR_HP_G54,
+ BCM47XX_BOARD_BUFFALO_WLA2_G54L,
+ BCM47XX_BOARD_BUFFALO_WZR_G300N,
+ BCM47XX_BOARD_BUFFALO_WZR_RS_G54,
+ BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP,
+
+ BCM47XX_BOARD_CISCO_M10V1,
+ BCM47XX_BOARD_CISCO_M20V1,
+
+ BCM47XX_BOARD_DELL_TM2300,
+
+ BCM47XX_BOARD_DLINK_DIR130,
+ BCM47XX_BOARD_DLINK_DIR330,
+
+ BCM47XX_BOARD_HUAWEI_E970,
+
+ BCM47XX_BOARD_LINKSYS_E900V1,
+ BCM47XX_BOARD_LINKSYS_E1000V1,
+ BCM47XX_BOARD_LINKSYS_E1000V2,
+ BCM47XX_BOARD_LINKSYS_E1000V21,
+ BCM47XX_BOARD_LINKSYS_E1200V2,
+ BCM47XX_BOARD_LINKSYS_E2000V1,
+ BCM47XX_BOARD_LINKSYS_E3000V1,
+ BCM47XX_BOARD_LINKSYS_E3200V1,
+ BCM47XX_BOARD_LINKSYS_E4200V1,
+ BCM47XX_BOARD_LINKSYS_WRT150NV1,
+ BCM47XX_BOARD_LINKSYS_WRT150NV11,
+ BCM47XX_BOARD_LINKSYS_WRT160NV1,
+ BCM47XX_BOARD_LINKSYS_WRT160NV3,
+ BCM47XX_BOARD_LINKSYS_WRT300NV11,
+ BCM47XX_BOARD_LINKSYS_WRT310NV1,
+ BCM47XX_BOARD_LINKSYS_WRT310NV2,
+ BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
+ BCM47XX_BOARD_LINKSYS_WRT54G,
+ BCM47XX_BOARD_LINKSYS_WRT610NV1,
+ BCM47XX_BOARD_LINKSYS_WRT610NV2,
+ BCM47XX_BOARD_LINKSYS_WRTSL54GS,
+
+ BCM47XX_BOARD_MOTOROLA_WE800G,
+ BCM47XX_BOARD_MOTOROLA_WR850GP,
+ BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
+
+ BCM47XX_BOARD_NETGEAR_WGR614V8,
+ BCM47XX_BOARD_NETGEAR_WGR614V9,
+ BCM47XX_BOARD_NETGEAR_WNDR3300,
+ BCM47XX_BOARD_NETGEAR_WNDR3400V1,
+ BCM47XX_BOARD_NETGEAR_WNDR3400V2,
+ BCM47XX_BOARD_NETGEAR_WNDR3400VCNA,
+ BCM47XX_BOARD_NETGEAR_WNDR3700V3,
+ BCM47XX_BOARD_NETGEAR_WNDR4000,
+ BCM47XX_BOARD_NETGEAR_WNDR4500V1,
+ BCM47XX_BOARD_NETGEAR_WNDR4500V2,
+ BCM47XX_BOARD_NETGEAR_WNR2000,
+ BCM47XX_BOARD_NETGEAR_WNR3500L,
+ BCM47XX_BOARD_NETGEAR_WNR3500U,
+ BCM47XX_BOARD_NETGEAR_WNR3500V2,
+ BCM47XX_BOARD_NETGEAR_WNR3500V2VC,
+ BCM47XX_BOARD_NETGEAR_WNR834BV2,
+
+ BCM47XX_BOARD_PHICOMM_M1,
+
+ BCM47XX_BOARD_SIEMENS_SE505V2,
+
+ BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE,
+
+ BCM47XX_BOARD_ZTE_H218N,
+
+ BCM47XX_BOARD_UNKNOWN,
+ BCM47XX_BOARD_NO,
+};
+
+#define BCM47XX_BOARD_MAX_NAME 30
+
+void bcm47xx_board_detect(void);
+enum bcm47xx_board bcm47xx_board_get(void);
+const char *bcm47xx_board_get_name(void);
+
+#endif /* __BCM47XX_BOARD_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
index b8e7be8f34d..36a3fc1aa3a 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
@@ -48,4 +48,6 @@ static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
}
+int bcm47xx_nvram_gpio_pin(const char *name);
+
#endif /* __BCM47XX_NVRAM_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h
new file mode 100644
index 00000000000..b7992cd4aaf
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h
@@ -0,0 +1,82 @@
+#ifndef __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_tlb 1
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 1
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 0
+#define cpu_has_32fpr 0
+#define cpu_has_counter 1
+#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB)
+#define cpu_has_watch 1
+#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA)
+#define cpu_has_watch 0
+#endif
+#define cpu_has_divec 1
+#define cpu_has_vce 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_cache_cdex_s 0
+#define cpu_has_prefetch 1
+#define cpu_has_mcheck 1
+#define cpu_has_ejtag 1
+#define cpu_has_llsc 1
+
+/* cpu_has_mips16 */
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_rixi 0
+#define cpu_has_mmips 0
+#define cpu_has_smartmips 0
+#define cpu_has_vtag_icache 0
+/* cpu_has_dc_aliases */
+#define cpu_has_ic_fills_f_dc 0
+#define cpu_has_pindexed_dcache 0
+#define cpu_icache_snoops_remote_store 0
+
+#define cpu_has_mips_2 1
+#define cpu_has_mips_3 0
+#define cpu_has_mips32r1 1
+#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB)
+#define cpu_has_mips32r2 1
+#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA)
+#define cpu_has_mips32r2 0
+#endif
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
+#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB)
+#define cpu_has_dsp 1
+#define cpu_has_dsp2 1
+#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA)
+#define cpu_has_dsp 0
+#define cpu_has_dsp2 0
+#endif
+#define cpu_has_mipsmt 0
+/* cpu_has_userlocal */
+
+#define cpu_has_nofpuex 0
+#define cpu_has_64bits 0
+#define cpu_has_64bit_zero_reg 0
+#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB)
+#define cpu_has_vint 1
+#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA)
+#define cpu_has_vint 0
+#endif
+#define cpu_has_veic 0
+#define cpu_has_inclusive_pcaches 0
+
+#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB)
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 32
+#define cpu_has_perf_cntr_intr_bit 1
+#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA)
+#define cpu_dcache_line_size() 16
+#define cpu_icache_line_size() 16
+#define cpu_has_perf_cntr_intr_bit 0
+#endif
+#define cpu_scache_line_size() 0
+#define cpu_has_vz 0
+
+#endif /* __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
index 19f9134bfe2..3112f08f0c7 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -145,6 +145,7 @@ enum bcm63xx_regs_set {
RSET_UART1,
RSET_GPIO,
RSET_SPI,
+ RSET_HSSPI,
RSET_UDC0,
RSET_OHCI0,
RSET_OHCI_PRIV,
@@ -193,6 +194,7 @@ enum bcm63xx_regs_set {
#define RSET_ENETDMAS_SIZE(chans) (16 * (chans))
#define RSET_ENETSW_SIZE 65536
#define RSET_UART_SIZE 24
+#define RSET_HSSPI_SIZE 1536
#define RSET_UDC_SIZE 256
#define RSET_OHCI_SIZE 256
#define RSET_EHCI_SIZE 256
@@ -265,6 +267,7 @@ enum bcm63xx_regs_set {
#define BCM_6328_UART1_BASE (0xb0000120)
#define BCM_6328_GPIO_BASE (0xb0000080)
#define BCM_6328_SPI_BASE (0xdeadbeef)
+#define BCM_6328_HSSPI_BASE (0xb0001000)
#define BCM_6328_UDC0_BASE (0xdeadbeef)
#define BCM_6328_USBDMA_BASE (0xb000c000)
#define BCM_6328_OHCI0_BASE (0xb0002600)
@@ -313,6 +316,7 @@ enum bcm63xx_regs_set {
#define BCM_6338_UART1_BASE (0xdeadbeef)
#define BCM_6338_GPIO_BASE (0xfffe0400)
#define BCM_6338_SPI_BASE (0xfffe0c00)
+#define BCM_6338_HSSPI_BASE (0xdeadbeef)
#define BCM_6338_UDC0_BASE (0xdeadbeef)
#define BCM_6338_USBDMA_BASE (0xfffe2400)
#define BCM_6338_OHCI0_BASE (0xdeadbeef)
@@ -360,6 +364,7 @@ enum bcm63xx_regs_set {
#define BCM_6345_UART1_BASE (0xdeadbeef)
#define BCM_6345_GPIO_BASE (0xfffe0400)
#define BCM_6345_SPI_BASE (0xdeadbeef)
+#define BCM_6345_HSSPI_BASE (0xdeadbeef)
#define BCM_6345_UDC0_BASE (0xdeadbeef)
#define BCM_6345_USBDMA_BASE (0xfffe2800)
#define BCM_6345_ENET0_BASE (0xfffe1800)
@@ -406,6 +411,7 @@ enum bcm63xx_regs_set {
#define BCM_6348_UART1_BASE (0xdeadbeef)
#define BCM_6348_GPIO_BASE (0xfffe0400)
#define BCM_6348_SPI_BASE (0xfffe0c00)
+#define BCM_6348_HSSPI_BASE (0xdeadbeef)
#define BCM_6348_UDC0_BASE (0xfffe1000)
#define BCM_6348_USBDMA_BASE (0xdeadbeef)
#define BCM_6348_OHCI0_BASE (0xfffe1b00)
@@ -451,6 +457,7 @@ enum bcm63xx_regs_set {
#define BCM_6358_UART1_BASE (0xfffe0120)
#define BCM_6358_GPIO_BASE (0xfffe0080)
#define BCM_6358_SPI_BASE (0xfffe0800)
+#define BCM_6358_HSSPI_BASE (0xdeadbeef)
#define BCM_6358_UDC0_BASE (0xfffe0800)
#define BCM_6358_USBDMA_BASE (0xdeadbeef)
#define BCM_6358_OHCI0_BASE (0xfffe1400)
@@ -553,6 +560,7 @@ enum bcm63xx_regs_set {
#define BCM_6368_UART1_BASE (0xb0000120)
#define BCM_6368_GPIO_BASE (0xb0000080)
#define BCM_6368_SPI_BASE (0xb0000800)
+#define BCM_6368_HSSPI_BASE (0xdeadbeef)
#define BCM_6368_UDC0_BASE (0xdeadbeef)
#define BCM_6368_USBDMA_BASE (0xb0004800)
#define BCM_6368_OHCI0_BASE (0xb0001600)
@@ -604,6 +612,7 @@ extern const unsigned long *bcm63xx_regs_base;
__GEN_RSET_BASE(__cpu, UART1) \
__GEN_RSET_BASE(__cpu, GPIO) \
__GEN_RSET_BASE(__cpu, SPI) \
+ __GEN_RSET_BASE(__cpu, HSSPI) \
__GEN_RSET_BASE(__cpu, UDC0) \
__GEN_RSET_BASE(__cpu, OHCI0) \
__GEN_RSET_BASE(__cpu, OHCI_PRIV) \
@@ -647,6 +656,7 @@ extern const unsigned long *bcm63xx_regs_base;
[RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \
[RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \
[RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \
+ [RSET_HSSPI] = BCM_## __cpu ##_HSSPI_BASE, \
[RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \
[RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \
[RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \
@@ -727,6 +737,7 @@ enum bcm63xx_irq {
IRQ_ENET0,
IRQ_ENET1,
IRQ_ENET_PHY,
+ IRQ_HSSPI,
IRQ_OHCI0,
IRQ_EHCI0,
IRQ_USBD,
@@ -815,6 +826,7 @@ enum bcm63xx_irq {
#define BCM_6328_ENET0_IRQ 0
#define BCM_6328_ENET1_IRQ 0
#define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
+#define BCM_6328_HSSPI_IRQ (IRQ_INTERNAL_BASE + 29)
#define BCM_6328_OHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 9)
#define BCM_6328_EHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 10)
#define BCM_6328_USBD_IRQ (IRQ_INTERNAL_BASE + 4)
@@ -860,6 +872,7 @@ enum bcm63xx_irq {
#define BCM_6338_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6338_ENET1_IRQ 0
#define BCM_6338_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_6338_HSSPI_IRQ 0
#define BCM_6338_OHCI0_IRQ 0
#define BCM_6338_EHCI0_IRQ 0
#define BCM_6338_USBD_IRQ 0
@@ -898,6 +911,7 @@ enum bcm63xx_irq {
#define BCM_6345_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6345_ENET1_IRQ 0
#define BCM_6345_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
+#define BCM_6345_HSSPI_IRQ 0
#define BCM_6345_OHCI0_IRQ 0
#define BCM_6345_EHCI0_IRQ 0
#define BCM_6345_USBD_IRQ 0
@@ -936,6 +950,7 @@ enum bcm63xx_irq {
#define BCM_6348_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6348_ENET1_IRQ (IRQ_INTERNAL_BASE + 7)
#define BCM_6348_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_6348_HSSPI_IRQ 0
#define BCM_6348_OHCI0_IRQ (IRQ_INTERNAL_BASE + 12)
#define BCM_6348_EHCI0_IRQ 0
#define BCM_6348_USBD_IRQ 0
@@ -974,6 +989,7 @@ enum bcm63xx_irq {
#define BCM_6358_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
#define BCM_6358_ENET1_IRQ (IRQ_INTERNAL_BASE + 6)
#define BCM_6358_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
+#define BCM_6358_HSSPI_IRQ 0
#define BCM_6358_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5)
#define BCM_6358_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
#define BCM_6358_USBD_IRQ 0
@@ -1086,6 +1102,7 @@ enum bcm63xx_irq {
#define BCM_6368_ENET0_IRQ 0
#define BCM_6368_ENET1_IRQ 0
#define BCM_6368_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 15)
+#define BCM_6368_HSSPI_IRQ 0
#define BCM_6368_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5)
#define BCM_6368_EHCI0_IRQ (IRQ_INTERNAL_BASE + 7)
#define BCM_6368_USBD_IRQ (IRQ_INTERNAL_BASE + 8)
@@ -1133,6 +1150,7 @@ extern const int *bcm63xx_irqs;
[IRQ_ENET0] = BCM_## __cpu ##_ENET0_IRQ, \
[IRQ_ENET1] = BCM_## __cpu ##_ENET1_IRQ, \
[IRQ_ENET_PHY] = BCM_## __cpu ##_ENET_PHY_IRQ, \
+ [IRQ_HSSPI] = BCM_## __cpu ##_HSSPI_IRQ, \
[IRQ_OHCI0] = BCM_## __cpu ##_OHCI0_IRQ, \
[IRQ_EHCI0] = BCM_## __cpu ##_EHCI0_IRQ, \
[IRQ_USBD] = BCM_## __cpu ##_USBD_IRQ, \
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
new file mode 100644
index 00000000000..1b1acafb3d7
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
@@ -0,0 +1,8 @@
+#ifndef BCM63XX_DEV_HSSPI_H
+#define BCM63XX_DEV_HSSPI_H
+
+#include <linux/types.h>
+
+int bcm63xx_hsspi_register(void);
+
+#endif /* BCM63XX_DEV_HSSPI_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 9875db31d88..ab427f8814e 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -463,126 +463,6 @@
#define WDT_SOFTRESET_REG 0xc
/*************************************************************************
- * _REG relative to RSET_UARTx
- *************************************************************************/
-
-/* UART Control Register */
-#define UART_CTL_REG 0x0
-#define UART_CTL_RXTMOUTCNT_SHIFT 0
-#define UART_CTL_RXTMOUTCNT_MASK (0x1f << UART_CTL_RXTMOUTCNT_SHIFT)
-#define UART_CTL_RSTTXDN_SHIFT 5
-#define UART_CTL_RSTTXDN_MASK (1 << UART_CTL_RSTTXDN_SHIFT)
-#define UART_CTL_RSTRXFIFO_SHIFT 6
-#define UART_CTL_RSTRXFIFO_MASK (1 << UART_CTL_RSTRXFIFO_SHIFT)
-#define UART_CTL_RSTTXFIFO_SHIFT 7
-#define UART_CTL_RSTTXFIFO_MASK (1 << UART_CTL_RSTTXFIFO_SHIFT)
-#define UART_CTL_STOPBITS_SHIFT 8
-#define UART_CTL_STOPBITS_MASK (0xf << UART_CTL_STOPBITS_SHIFT)
-#define UART_CTL_STOPBITS_1 (0x7 << UART_CTL_STOPBITS_SHIFT)
-#define UART_CTL_STOPBITS_2 (0xf << UART_CTL_STOPBITS_SHIFT)
-#define UART_CTL_BITSPERSYM_SHIFT 12
-#define UART_CTL_BITSPERSYM_MASK (0x3 << UART_CTL_BITSPERSYM_SHIFT)
-#define UART_CTL_XMITBRK_SHIFT 14
-#define UART_CTL_XMITBRK_MASK (1 << UART_CTL_XMITBRK_SHIFT)
-#define UART_CTL_RSVD_SHIFT 15
-#define UART_CTL_RSVD_MASK (1 << UART_CTL_RSVD_SHIFT)
-#define UART_CTL_RXPAREVEN_SHIFT 16
-#define UART_CTL_RXPAREVEN_MASK (1 << UART_CTL_RXPAREVEN_SHIFT)
-#define UART_CTL_RXPAREN_SHIFT 17
-#define UART_CTL_RXPAREN_MASK (1 << UART_CTL_RXPAREN_SHIFT)
-#define UART_CTL_TXPAREVEN_SHIFT 18
-#define UART_CTL_TXPAREVEN_MASK (1 << UART_CTL_TXPAREVEN_SHIFT)
-#define UART_CTL_TXPAREN_SHIFT 18
-#define UART_CTL_TXPAREN_MASK (1 << UART_CTL_TXPAREN_SHIFT)
-#define UART_CTL_LOOPBACK_SHIFT 20
-#define UART_CTL_LOOPBACK_MASK (1 << UART_CTL_LOOPBACK_SHIFT)
-#define UART_CTL_RXEN_SHIFT 21
-#define UART_CTL_RXEN_MASK (1 << UART_CTL_RXEN_SHIFT)
-#define UART_CTL_TXEN_SHIFT 22
-#define UART_CTL_TXEN_MASK (1 << UART_CTL_TXEN_SHIFT)
-#define UART_CTL_BRGEN_SHIFT 23
-#define UART_CTL_BRGEN_MASK (1 << UART_CTL_BRGEN_SHIFT)
-
-/* UART Baudword register */
-#define UART_BAUD_REG 0x4
-
-/* UART Misc Control register */
-#define UART_MCTL_REG 0x8
-#define UART_MCTL_DTR_SHIFT 0
-#define UART_MCTL_DTR_MASK (1 << UART_MCTL_DTR_SHIFT)
-#define UART_MCTL_RTS_SHIFT 1
-#define UART_MCTL_RTS_MASK (1 << UART_MCTL_RTS_SHIFT)
-#define UART_MCTL_RXFIFOTHRESH_SHIFT 8
-#define UART_MCTL_RXFIFOTHRESH_MASK (0xf << UART_MCTL_RXFIFOTHRESH_SHIFT)
-#define UART_MCTL_TXFIFOTHRESH_SHIFT 12
-#define UART_MCTL_TXFIFOTHRESH_MASK (0xf << UART_MCTL_TXFIFOTHRESH_SHIFT)
-#define UART_MCTL_RXFIFOFILL_SHIFT 16
-#define UART_MCTL_RXFIFOFILL_MASK (0x1f << UART_MCTL_RXFIFOFILL_SHIFT)
-#define UART_MCTL_TXFIFOFILL_SHIFT 24
-#define UART_MCTL_TXFIFOFILL_MASK (0x1f << UART_MCTL_TXFIFOFILL_SHIFT)
-
-/* UART External Input Configuration register */
-#define UART_EXTINP_REG 0xc
-#define UART_EXTINP_RI_SHIFT 0
-#define UART_EXTINP_RI_MASK (1 << UART_EXTINP_RI_SHIFT)
-#define UART_EXTINP_CTS_SHIFT 1
-#define UART_EXTINP_CTS_MASK (1 << UART_EXTINP_CTS_SHIFT)
-#define UART_EXTINP_DCD_SHIFT 2
-#define UART_EXTINP_DCD_MASK (1 << UART_EXTINP_DCD_SHIFT)
-#define UART_EXTINP_DSR_SHIFT 3
-#define UART_EXTINP_DSR_MASK (1 << UART_EXTINP_DSR_SHIFT)
-#define UART_EXTINP_IRSTAT(x) (1 << (x + 4))
-#define UART_EXTINP_IRMASK(x) (1 << (x + 8))
-#define UART_EXTINP_IR_RI 0
-#define UART_EXTINP_IR_CTS 1
-#define UART_EXTINP_IR_DCD 2
-#define UART_EXTINP_IR_DSR 3
-#define UART_EXTINP_RI_NOSENSE_SHIFT 16
-#define UART_EXTINP_RI_NOSENSE_MASK (1 << UART_EXTINP_RI_NOSENSE_SHIFT)
-#define UART_EXTINP_CTS_NOSENSE_SHIFT 17
-#define UART_EXTINP_CTS_NOSENSE_MASK (1 << UART_EXTINP_CTS_NOSENSE_SHIFT)
-#define UART_EXTINP_DCD_NOSENSE_SHIFT 18
-#define UART_EXTINP_DCD_NOSENSE_MASK (1 << UART_EXTINP_DCD_NOSENSE_SHIFT)
-#define UART_EXTINP_DSR_NOSENSE_SHIFT 19
-#define UART_EXTINP_DSR_NOSENSE_MASK (1 << UART_EXTINP_DSR_NOSENSE_SHIFT)
-
-/* UART Interrupt register */
-#define UART_IR_REG 0x10
-#define UART_IR_MASK(x) (1 << (x + 16))
-#define UART_IR_STAT(x) (1 << (x))
-#define UART_IR_EXTIP 0
-#define UART_IR_TXUNDER 1
-#define UART_IR_TXOVER 2
-#define UART_IR_TXTRESH 3
-#define UART_IR_TXRDLATCH 4
-#define UART_IR_TXEMPTY 5
-#define UART_IR_RXUNDER 6
-#define UART_IR_RXOVER 7
-#define UART_IR_RXTIMEOUT 8
-#define UART_IR_RXFULL 9
-#define UART_IR_RXTHRESH 10
-#define UART_IR_RXNOTEMPTY 11
-#define UART_IR_RXFRAMEERR 12
-#define UART_IR_RXPARERR 13
-#define UART_IR_RXBRK 14
-#define UART_IR_TXDONE 15
-
-/* UART Fifo register */
-#define UART_FIFO_REG 0x14
-#define UART_FIFO_VALID_SHIFT 0
-#define UART_FIFO_VALID_MASK 0xff
-#define UART_FIFO_FRAMEERR_SHIFT 8
-#define UART_FIFO_FRAMEERR_MASK (1 << UART_FIFO_FRAMEERR_SHIFT)
-#define UART_FIFO_PARERR_SHIFT 9
-#define UART_FIFO_PARERR_MASK (1 << UART_FIFO_PARERR_SHIFT)
-#define UART_FIFO_BRKDET_SHIFT 10
-#define UART_FIFO_BRKDET_MASK (1 << UART_FIFO_BRKDET_SHIFT)
-#define UART_FIFO_ANYERR_MASK (UART_FIFO_FRAMEERR_MASK | \
- UART_FIFO_PARERR_MASK | \
- UART_FIFO_BRKDET_MASK)
-
-
-/*************************************************************************
* _REG relative to RSET_GPIO
*************************************************************************/
diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
index 94ed063eec9..cf802287289 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
@@ -22,7 +22,6 @@
#define cpu_has_3k_cache 0
#define cpu_has_4k_cache 0
#define cpu_has_tx39_cache 0
-#define cpu_has_fpu 0
#define cpu_has_counter 1
#define cpu_has_watch 1
#define cpu_has_divec 1
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 47fb247f966..f9f44865050 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -52,23 +52,11 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 0;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
- BUG();
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 1;
}
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- BUG();
- return 0;
-}
-
dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h
index 60fc4c347c4..cceae32a073 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/irq.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h
@@ -35,6 +35,8 @@ enum octeon_irq {
OCTEON_IRQ_PCI_MSI2,
OCTEON_IRQ_PCI_MSI3,
+ OCTEON_IRQ_TWSI,
+ OCTEON_IRQ_TWSI2,
OCTEON_IRQ_RML,
OCTEON_IRQ_TIMER0,
OCTEON_IRQ_TIMER1,
diff --git a/arch/mips/include/asm/mach-db1x00/db1200.h b/arch/mips/include/asm/mach-db1x00/db1200.h
deleted file mode 100644
index d3cce7326dd..00000000000
--- a/arch/mips/include/asm/mach-db1x00/db1200.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * AMD Alchemy DBAu1200 Reference Board
- * Board register defines.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- *
- */
-#ifndef __ASM_DB1200_H
-#define __ASM_DB1200_H
-
-#include <linux/types.h>
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/au1xxx_psc.h>
-
-/* Bit positions for the different interrupt sources */
-#define BCSR_INT_IDE 0x0001
-#define BCSR_INT_ETH 0x0002
-#define BCSR_INT_PC0 0x0004
-#define BCSR_INT_PC0STSCHG 0x0008
-#define BCSR_INT_PC1 0x0010
-#define BCSR_INT_PC1STSCHG 0x0020
-#define BCSR_INT_DC 0x0040
-#define BCSR_INT_FLASHBUSY 0x0080
-#define BCSR_INT_PC0INSERT 0x0100
-#define BCSR_INT_PC0EJECT 0x0200
-#define BCSR_INT_PC1INSERT 0x0400
-#define BCSR_INT_PC1EJECT 0x0800
-#define BCSR_INT_SD0INSERT 0x1000
-#define BCSR_INT_SD0EJECT 0x2000
-#define BCSR_INT_SD1INSERT 0x4000
-#define BCSR_INT_SD1EJECT 0x8000
-
-#define IDE_REG_SHIFT 5
-
-#define DB1200_IDE_PHYS_ADDR 0x18800000
-#define DB1200_IDE_PHYS_LEN (16 << IDE_REG_SHIFT)
-#define DB1200_ETH_PHYS_ADDR 0x19000300
-#define DB1200_NAND_PHYS_ADDR 0x20000000
-
-#define PB1200_IDE_PHYS_ADDR 0x0C800000
-#define PB1200_ETH_PHYS_ADDR 0x0D000300
-#define PB1200_NAND_PHYS_ADDR 0x1C000000
-
-/*
- * External Interrupts for DBAu1200 as of 8/6/2004.
- * Bit positions in the CPLD registers can be calculated by taking
- * the interrupt define and subtracting the DB1200_INT_BEGIN value.
- *
- * Example: IDE bis pos is = 64 - 64
- * ETH bit pos is = 65 - 64
- */
-enum external_db1200_ints {
- DB1200_INT_BEGIN = AU1000_MAX_INTR + 1,
-
- DB1200_IDE_INT = DB1200_INT_BEGIN,
- DB1200_ETH_INT,
- DB1200_PC0_INT,
- DB1200_PC0_STSCHG_INT,
- DB1200_PC1_INT,
- DB1200_PC1_STSCHG_INT,
- DB1200_DC_INT,
- DB1200_FLASHBUSY_INT,
- DB1200_PC0_INSERT_INT,
- DB1200_PC0_EJECT_INT,
- DB1200_PC1_INSERT_INT,
- DB1200_PC1_EJECT_INT,
- DB1200_SD0_INSERT_INT,
- DB1200_SD0_EJECT_INT,
- PB1200_SD1_INSERT_INT,
- PB1200_SD1_EJECT_INT,
-
- DB1200_INT_END = DB1200_INT_BEGIN + 15,
-};
-
-#endif /* __ASM_DB1200_H */
diff --git a/arch/mips/include/asm/mach-db1x00/db1300.h b/arch/mips/include/asm/mach-db1x00/db1300.h
deleted file mode 100644
index 3d1ede46f05..00000000000
--- a/arch/mips/include/asm/mach-db1x00/db1300.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * NetLogic DB1300 board constants
- */
-
-#ifndef _DB1300_H_
-#define _DB1300_H_
-
-/* FPGA (external mux) interrupt sources */
-#define DB1300_FIRST_INT (ALCHEMY_GPIC_INT_LAST + 1)
-#define DB1300_IDE_INT (DB1300_FIRST_INT + 0)
-#define DB1300_ETH_INT (DB1300_FIRST_INT + 1)
-#define DB1300_CF_INT (DB1300_FIRST_INT + 2)
-#define DB1300_VIDEO_INT (DB1300_FIRST_INT + 4)
-#define DB1300_HDMI_INT (DB1300_FIRST_INT + 5)
-#define DB1300_DC_INT (DB1300_FIRST_INT + 6)
-#define DB1300_FLASH_INT (DB1300_FIRST_INT + 7)
-#define DB1300_CF_INSERT_INT (DB1300_FIRST_INT + 8)
-#define DB1300_CF_EJECT_INT (DB1300_FIRST_INT + 9)
-#define DB1300_AC97_INT (DB1300_FIRST_INT + 10)
-#define DB1300_AC97_PEN_INT (DB1300_FIRST_INT + 11)
-#define DB1300_SD1_INSERT_INT (DB1300_FIRST_INT + 12)
-#define DB1300_SD1_EJECT_INT (DB1300_FIRST_INT + 13)
-#define DB1300_OTG_VBUS_OC_INT (DB1300_FIRST_INT + 14)
-#define DB1300_HOST_VBUS_OC_INT (DB1300_FIRST_INT + 15)
-#define DB1300_LAST_INT (DB1300_FIRST_INT + 15)
-
-/* SMSC9210 CS */
-#define DB1300_ETH_PHYS_ADDR 0x19000000
-#define DB1300_ETH_PHYS_END 0x197fffff
-
-/* ATA CS */
-#define DB1300_IDE_PHYS_ADDR 0x18800000
-#define DB1300_IDE_REG_SHIFT 5
-#define DB1300_IDE_PHYS_LEN (16 << DB1300_IDE_REG_SHIFT)
-
-/* NAND CS */
-#define DB1300_NAND_PHYS_ADDR 0x20000000
-#define DB1300_NAND_PHYS_END 0x20000fff
-
-#endif /* _DB1300_H_ */
diff --git a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
new file mode 100644
index 00000000000..acce27fd2bb
--- /dev/null
+++ b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
@@ -0,0 +1,87 @@
+/*
+ * CPU feature overrides for DECstation systems. Two variations
+ * are generally applicable.
+ *
+ * Copyright (C) 2013 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H
+
+/* Generic ones first. */
+#define cpu_has_tlb 1
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 1
+#define cpu_has_divec 0
+#define cpu_has_prefetch 0
+#define cpu_has_mcheck 0
+#define cpu_has_ejtag 0
+#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_vtag_icache 0
+#define cpu_has_ic_fills_f_dc 0
+#define cpu_has_pindexed_dcache 0
+#define cpu_has_local_ebase 0
+#define cpu_icache_snoops_remote_store 1
+#define cpu_has_mips_4 0
+#define cpu_has_mips_5 0
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+#define cpu_has_userlocal 0
+
+/* R3k-specific ones. */
+#ifdef CONFIG_CPU_R3000
+#define cpu_has_4kex 0
+#define cpu_has_3k_cache 1
+#define cpu_has_4k_cache 0
+#define cpu_has_32fpr 0
+#define cpu_has_counter 0
+#define cpu_has_watch 0
+#define cpu_has_vce 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_cache_cdex_s 0
+#define cpu_has_llsc 0
+#define cpu_has_dc_aliases 0
+#define cpu_has_mips_2 0
+#define cpu_has_mips_3 0
+#define cpu_has_nofpuex 1
+#define cpu_has_inclusive_pcaches 0
+#define cpu_dcache_line_size() 4
+#define cpu_icache_line_size() 4
+#define cpu_scache_line_size() 0
+#endif /* CONFIG_CPU_R3000 */
+
+/* R4k-specific ones. */
+#ifdef CONFIG_CPU_R4X00
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 1
+#define cpu_has_32fpr 1
+#define cpu_has_counter 1
+#define cpu_has_watch 1
+#define cpu_has_vce 1
+#define cpu_has_cache_cdex_p 1
+#define cpu_has_cache_cdex_s 1
+#define cpu_has_llsc 1
+#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
+#define cpu_has_mips_2 1
+#define cpu_has_mips_3 1
+#define cpu_has_nofpuex 0
+#define cpu_has_inclusive_pcaches 1
+#define cpu_dcache_line_size() 16
+#define cpu_icache_line_size() 16
+#define cpu_scache_line_size() 32
+#endif /* CONFIG_CPU_R4X00 */
+
+#endif /* __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 74cb99257d5..7629c35986f 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -47,23 +47,9 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
-#ifdef CONFIG_DMA_COHERENT
- return 1;
-#else
return coherentio;
-#endif
}
#ifdef CONFIG_SWIOTLB
diff --git a/arch/mips/include/asm/mach-generic/floppy.h b/arch/mips/include/asm/mach-generic/floppy.h
index 5b5cd689a2f..e2561d99a3f 100644
--- a/arch/mips/include/asm/mach-generic/floppy.h
+++ b/arch/mips/include/asm/mach-generic/floppy.h
@@ -9,7 +9,6 @@
#define __ASM_MACH_GENERIC_FLOPPY_H
#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/linkage.h>
diff --git a/arch/mips/include/asm/mach-generic/ide.h b/arch/mips/include/asm/mach-generic/ide.h
index affa66f5c2d..4ae5fbcb15a 100644
--- a/arch/mips/include/asm/mach-generic/ide.h
+++ b/arch/mips/include/asm/mach-generic/ide.h
@@ -23,7 +23,7 @@
static inline void __ide_flush_prologue(void)
{
#ifdef CONFIG_SMP
- if (cpu_has_dc_aliases)
+ if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
preempt_disable();
#endif
}
@@ -31,14 +31,14 @@ static inline void __ide_flush_prologue(void)
static inline void __ide_flush_epilogue(void)
{
#ifdef CONFIG_SMP
- if (cpu_has_dc_aliases)
+ if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
preempt_enable();
#endif
}
static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
{
- if (cpu_has_dc_aliases) {
+ if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) {
unsigned long end = addr + size;
while (addr < end) {
diff --git a/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h
index f4caacd2555..1dfe47453ea 100644
--- a/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h
@@ -8,6 +8,8 @@
#ifndef __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H
#define __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H
+#include <asm/cpu.h>
+
/*
* IP22 with a variety of processors so we can't use defaults for everything.
*/
@@ -37,6 +39,10 @@
#define cpu_has_nofpuex 0
#define cpu_has_64bits 1
+#define cpu_has_mips_2 1
+#define cpu_has_mips_3 1
+#define cpu_has_mips_5 0
+
#define cpu_has_mips32r1 0
#define cpu_has_mips32r2 0
#define cpu_has_mips64r1 0
diff --git a/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
index 1d2b6ff60d3..d6111aa2e88 100644
--- a/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
@@ -8,6 +8,8 @@
#ifndef __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H
#define __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H
+#include <asm/cpu.h>
+
/*
* IP27 only comes with R10000 family processors all using the same config
*/
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index 06c441968e6..4ffddfdb506 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -58,16 +58,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 1; /* IP27 non-cohernet mode is unsupported */
diff --git a/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h
index 65e9c856390..4cec06d133d 100644
--- a/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h
@@ -9,6 +9,8 @@
#ifndef __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H
#define __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H
+#include <asm/cpu.h>
+
/*
* IP28 only comes with R10000 family processors all using the same config
*/
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index 073f0c4760b..104cfbc3ed6 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -80,17 +80,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
- return;
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 0; /* IP32 is non-cohernet */
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index 9fc1e9ad703..949003ef97b 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -48,16 +48,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 0;
diff --git a/arch/mips/include/asm/mach-jazz/floppy.h b/arch/mips/include/asm/mach-jazz/floppy.h
index 62aa1e287fb..4b86c88a03b 100644
--- a/arch/mips/include/asm/mach-jazz/floppy.h
+++ b/arch/mips/include/asm/mach-jazz/floppy.h
@@ -9,7 +9,6 @@
#define __ASM_MACH_JAZZ_FLOPPY_H
#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/types.h>
#include <linux/mm.h>
diff --git a/arch/mips/include/asm/mach-jz4740/dma.h b/arch/mips/include/asm/mach-jz4740/dma.h
index 509cd582804..14ecc5313d2 100644
--- a/arch/mips/include/asm/mach-jz4740/dma.h
+++ b/arch/mips/include/asm/mach-jz4740/dma.h
@@ -22,8 +22,6 @@ enum jz4740_dma_request_type {
JZ4740_DMA_TYPE_UART_RECEIVE = 21,
JZ4740_DMA_TYPE_SPI_TRANSMIT = 22,
JZ4740_DMA_TYPE_SPI_RECEIVE = 23,
- JZ4740_DMA_TYPE_AIC_TRANSMIT = 24,
- JZ4740_DMA_TYPE_AIC_RECEIVE = 25,
JZ4740_DMA_TYPE_MMC_TRANSMIT = 26,
JZ4740_DMA_TYPE_MMC_RECEIVE = 27,
JZ4740_DMA_TYPE_TCU = 28,
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
index 05988c2d656..069b43a9da6 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -21,6 +21,7 @@
extern struct platform_device jz4740_usb_ohci_device;
extern struct platform_device jz4740_udc_device;
+extern struct platform_device jz4740_udc_xceiv_device;
extern struct platform_device jz4740_mmc_device;
extern struct platform_device jz4740_rtc_device;
extern struct platform_device jz4740_i2c_device;
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
new file mode 100644
index 00000000000..829a7ec185f
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -0,0 +1,163 @@
+#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
+#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
+
+#define SYSTEM_RAM_LOW 1
+#define SYSTEM_RAM_HIGH 2
+#define MEM_RESERVED 3
+#define PCI_IO 4
+#define PCI_MEM 5
+#define LOONGSON_CFG_REG 6
+#define VIDEO_ROM 7
+#define ADAPTER_ROM 8
+#define ACPI_TABLE 9
+#define MAX_MEMORY_TYPE 10
+
+#define LOONGSON3_BOOT_MEM_MAP_MAX 128
+struct efi_memory_map_loongson {
+ u16 vers; /* version of efi_memory_map */
+ u32 nr_map; /* number of memory_maps */
+ u32 mem_freq; /* memory frequence */
+ struct mem_map {
+ u32 node_id; /* node_id which memory attached to */
+ u32 mem_type; /* system memory, pci memory, pci io, etc. */
+ u64 mem_start; /* memory map start address */
+ u32 mem_size; /* each memory_map size, not the total size */
+ } map[LOONGSON3_BOOT_MEM_MAP_MAX];
+} __packed;
+
+enum loongson_cpu_type {
+ Loongson_2E = 0,
+ Loongson_2F = 1,
+ Loongson_3A = 2,
+ Loongson_3B = 3,
+ Loongson_1A = 4,
+ Loongson_1B = 5
+};
+
+/*
+ * Capability and feature descriptor structure for MIPS CPU
+ */
+struct efi_cpuinfo_loongson {
+ u16 vers; /* version of efi_cpuinfo_loongson */
+ u32 processor_id; /* PRID, e.g. 6305, 6306 */
+ u32 cputype; /* Loongson_3A/3B, etc. */
+ u32 total_node; /* num of total numa nodes */
+ u32 cpu_startup_core_id; /* Core id */
+ u32 cpu_clock_freq; /* cpu_clock */
+ u32 nr_cpus;
+} __packed;
+
+struct system_loongson {
+ u16 vers; /* version of system_loongson */
+ u32 ccnuma_smp; /* 0: no numa; 1: has numa */
+ u32 sing_double_channel; /* 1:single; 2:double */
+} __packed;
+
+struct irq_source_routing_table {
+ u16 vers;
+ u16 size;
+ u16 rtr_bus;
+ u16 rtr_devfn;
+ u32 vendor;
+ u32 device;
+ u32 PIC_type; /* conform use HT or PCI to route to CPU-PIC */
+ u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
+ u64 ht_enable; /* irqs used in this PIC */
+ u32 node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
+ u64 pci_mem_start_addr;
+ u64 pci_mem_end_addr;
+ u64 pci_io_start_addr;
+ u64 pci_io_end_addr;
+ u64 pci_config_addr;
+ u32 dma_mask_bits;
+} __packed;
+
+struct interface_info {
+ u16 vers; /* version of the specificition */
+ u16 size;
+ u8 flag;
+ char description[64];
+} __packed;
+
+#define MAX_RESOURCE_NUMBER 128
+struct resource_loongson {
+ u64 start; /* resource start address */
+ u64 end; /* resource end address */
+ char name[64];
+ u32 flags;
+};
+
+struct archdev_data {}; /* arch specific additions */
+
+struct board_devices {
+ char name[64]; /* hold the device name */
+ u32 num_resources; /* number of device_resource */
+ /* for each device's resource */
+ struct resource_loongson resource[MAX_RESOURCE_NUMBER];
+ /* arch specific additions */
+ struct archdev_data archdata;
+};
+
+struct loongson_special_attribute {
+ u16 vers; /* version of this special */
+ char special_name[64]; /* special_atribute_name */
+ u32 loongson_special_type; /* type of special device */
+ /* for each device's resource */
+ struct resource_loongson resource[MAX_RESOURCE_NUMBER];
+};
+
+struct loongson_params {
+ u64 memory_offset; /* efi_memory_map_loongson struct offset */
+ u64 cpu_offset; /* efi_cpuinfo_loongson struct offset */
+ u64 system_offset; /* system_loongson struct offset */
+ u64 irq_offset; /* irq_source_routing_table struct offset */
+ u64 interface_offset; /* interface_info struct offset */
+ u64 special_offset; /* loongson_special_attribute struct offset */
+ u64 boarddev_table_offset; /* board_devices offset */
+};
+
+struct smbios_tables {
+ u16 vers; /* version of smbios */
+ u64 vga_bios; /* vga_bios address */
+ struct loongson_params lp;
+};
+
+struct efi_reset_system_t {
+ u64 ResetCold;
+ u64 ResetWarm;
+ u64 ResetType;
+ u64 Shutdown;
+ u64 DoSuspend; /* NULL if not support */
+};
+
+struct efi_loongson {
+ u64 mps; /* MPS table */
+ u64 acpi; /* ACPI table (IA64 ext 0.71) */
+ u64 acpi20; /* ACPI table (ACPI 2.0) */
+ struct smbios_tables smbios; /* SM BIOS table */
+ u64 sal_systab; /* SAL system table */
+ u64 boot_info; /* boot info table */
+};
+
+struct boot_params {
+ struct efi_loongson efi;
+ struct efi_reset_system_t reset_system;
+};
+
+struct loongson_system_configuration {
+ u32 nr_cpus;
+ enum loongson_cpu_type cputype;
+ u64 ht_control_base;
+ u64 pci_mem_start_addr;
+ u64 pci_mem_end_addr;
+ u64 pci_io_base;
+ u64 restart_addr;
+ u64 poweroff_addr;
+ u64 suspend_addr;
+ u64 vgabios_addr;
+ u32 dma_mask_bits;
+};
+
+extern struct efi_memory_map_loongson *loongson_memmap;
+extern struct loongson_system_configuration loongson_sysconf;
+#endif
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index e1433055fe9..6a902751cc7 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -11,24 +11,40 @@
#ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
#define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
+#ifdef CONFIG_SWIOTLB
+#include <linux/swiotlb.h>
+#endif
+
struct device;
+extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
+extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
size_t size)
{
+#ifdef CONFIG_CPU_LOONGSON3
+ return virt_to_phys(addr);
+#else
return virt_to_phys(addr) | 0x80000000;
+#endif
}
static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
struct page *page)
{
+#ifdef CONFIG_CPU_LOONGSON3
+ return page_to_phys(page);
+#else
return page_to_phys(page) | 0x80000000;
+#endif
}
static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
dma_addr_t dma_addr)
{
-#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
+ return dma_addr;
+#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
#else
return dma_addr & 0x7fffffff;
@@ -53,19 +69,13 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
+#ifdef CONFIG_DMA_NONCOHERENT
return 0;
+#else
+ return 1;
+#endif /* CONFIG_DMA_NONCOHERENT */
}
#endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
new file mode 100644
index 00000000000..34560bda662
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/irq.h
@@ -0,0 +1,44 @@
+#ifndef __ASM_MACH_LOONGSON_IRQ_H_
+#define __ASM_MACH_LOONGSON_IRQ_H_
+
+#include <boot_param.h>
+
+#ifdef CONFIG_CPU_LOONGSON3
+
+/* cpu core interrupt numbers */
+#define MIPS_CPU_IRQ_BASE 56
+
+#define LOONGSON_UART_IRQ (MIPS_CPU_IRQ_BASE + 2) /* UART */
+#define LOONGSON_HT1_IRQ (MIPS_CPU_IRQ_BASE + 3) /* HT1 */
+#define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7) /* CPU Timer */
+
+#define LOONGSON_HT1_CFG_BASE loongson_sysconf.ht_control_base
+#define LOONGSON_HT1_INT_VECTOR_BASE (LOONGSON_HT1_CFG_BASE + 0x80)
+#define LOONGSON_HT1_INT_EN_BASE (LOONGSON_HT1_CFG_BASE + 0xa0)
+#define LOONGSON_HT1_INT_VECTOR(n) \
+ LOONGSON3_REG32(LOONGSON_HT1_INT_VECTOR_BASE, 4 * (n))
+#define LOONGSON_HT1_INTN_EN(n) \
+ LOONGSON3_REG32(LOONGSON_HT1_INT_EN_BASE, 4 * (n))
+
+#define LOONGSON_INT_ROUTER_OFFSET 0x1400
+#define LOONGSON_INT_ROUTER_INTEN \
+ LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x24)
+#define LOONGSON_INT_ROUTER_INTENSET \
+ LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x28)
+#define LOONGSON_INT_ROUTER_INTENCLR \
+ LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x2c)
+#define LOONGSON_INT_ROUTER_ENTRY(n) \
+ LOONGSON3_REG8(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + n)
+#define LOONGSON_INT_ROUTER_LPC LOONGSON_INT_ROUTER_ENTRY(0x0a)
+#define LOONGSON_INT_ROUTER_HT1(n) LOONGSON_INT_ROUTER_ENTRY(n + 0x18)
+
+#define LOONGSON_INT_CORE0_INT0 0x11 /* route to int 0 of core 0 */
+#define LOONGSON_INT_CORE0_INT1 0x21 /* route to int 1 of core 0 */
+
+#endif
+
+extern void fixup_irqs(void);
+extern void loongson3_ipi_interrupt(struct pt_regs *regs);
+
+#include_next <irq.h>
+#endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index b286534fef0..f3fd1eb8e3d 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kconfig.h>
+#include <boot_param.h>
/* loongson internal northbridge initialization */
extern void bonito_irq_init(void);
@@ -24,8 +25,9 @@ extern void mach_prepare_reboot(void);
extern void mach_prepare_shutdown(void);
/* environment arguments from bootloader */
-extern unsigned long cpu_clock_freq;
-extern unsigned long memsize, highmemsize;
+extern u32 cpu_clock_freq;
+extern u32 memsize, highmemsize;
+extern struct plat_smp_ops loongson3_smp_ops;
/* loongson-specific command line, env and memory initialization */
extern void __init prom_init_memory(void);
@@ -61,6 +63,12 @@ extern int mach_i8259_irq(void);
#define LOONGSON_REG(x) \
(*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
+#define LOONGSON3_REG8(base, x) \
+ (*(volatile u8 *)((char *)TO_UNCAC(base) + (x)))
+
+#define LOONGSON3_REG32(base, x) \
+ (*(volatile u32 *)((char *)TO_UNCAC(base) + (x)))
+
#define LOONGSON_IRQ_BASE 32
#define LOONGSON2_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
@@ -86,6 +94,10 @@ static inline void do_perfcnt_IRQ(void)
#define LOONGSON_REG_BASE 0x1fe00000
#define LOONGSON_REG_SIZE 0x00100000 /* 256Bytes + 256Bytes + ??? */
#define LOONGSON_REG_TOP (LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
+/* Loongson-3 specific registers */
+#define LOONGSON3_REG_BASE 0x3ff00000
+#define LOONGSON3_REG_SIZE 0x00100000 /* 256Bytes + 256Bytes + ??? */
+#define LOONGSON3_REG_TOP (LOONGSON3_REG_BASE+LOONGSON3_REG_SIZE-1)
#define LOONGSON_LIO1_BASE 0x1ff00000
#define LOONGSON_LIO1_SIZE 0x00100000 /* 1M */
@@ -101,7 +113,13 @@ static inline void do_perfcnt_IRQ(void)
#define LOONGSON_PCICFG_BASE 0x1fe80000
#define LOONGSON_PCICFG_SIZE 0x00000800 /* 2K */
#define LOONGSON_PCICFG_TOP (LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
+
+#if defined(CONFIG_HT_PCI)
+#define LOONGSON_PCIIO_BASE loongson_sysconf.pci_io_base
+#else
#define LOONGSON_PCIIO_BASE 0x1fd00000
+#endif
+
#define LOONGSON_PCIIO_SIZE 0x00100000 /* 1M */
#define LOONGSON_PCIIO_TOP (LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
@@ -231,6 +249,9 @@ static inline void do_perfcnt_IRQ(void)
#define LOONGSON_PXARB_CFG LOONGSON_REG(LOONGSON_REGBASE + 0x68)
#define LOONGSON_PXARB_STATUS LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
+/* Chip Config */
+#define LOONGSON_CHIPCFG0 LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+
/* pcimap */
#define LOONGSON_PCIMAP_PCIMAP_LO0 0x0000003f
@@ -246,9 +267,6 @@ static inline void do_perfcnt_IRQ(void)
#ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
#include <linux/cpufreq.h>
extern struct cpufreq_frequency_table loongson2_clockmod_table[];
-
-/* Chip Config */
-#define LOONGSON_CHIPCFG0 LOONGSON_REG(LOONGSON_REGBASE + 0x80)
#endif
/*
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 3810d5ca84a..1b1f592fa2b 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -24,4 +24,10 @@
#endif
+#ifdef CONFIG_LEMOTE_MACH3A
+
+#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
+
+#endif /* CONFIG_LEMOTE_MACH3A */
+
#endif /* __ASM_MACH_LOONGSON_MACHINE_H */
diff --git a/arch/mips/include/asm/mach-loongson/pci.h b/arch/mips/include/asm/mach-loongson/pci.h
index bc99dab4ef6..1212774f66e 100644
--- a/arch/mips/include/asm/mach-loongson/pci.h
+++ b/arch/mips/include/asm/mach-loongson/pci.h
@@ -40,8 +40,13 @@ extern struct pci_ops loongson_pci_ops;
#else /* loongson2f/32bit & loongson2e */
/* this pci memory space is mapped by pcimap in pci.c */
+#ifdef CONFIG_CPU_LOONGSON3
+#define LOONGSON_PCI_MEM_START 0x40000000UL
+#define LOONGSON_PCI_MEM_END 0x7effffffUL
+#else
#define LOONGSON_PCI_MEM_START LOONGSON_PCILO1_BASE
#define LOONGSON_PCI_MEM_END (LOONGSON_PCILO1_BASE + 0x04000000 * 2)
+#endif
/* this is an offset from mips_io_port_base */
#define LOONGSON_PCI_IO_START 0x00004000UL
diff --git a/arch/mips/include/asm/mach-loongson/spaces.h b/arch/mips/include/asm/mach-loongson/spaces.h
new file mode 100644
index 00000000000..e2506ee9004
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/spaces.h
@@ -0,0 +1,9 @@
+#ifndef __ASM_MACH_LOONGSON_SPACES_H_
+#define __ASM_MACH_LOONGSON_SPACES_H_
+
+#if defined(CONFIG_64BIT)
+#define CAC_BASE _AC(0x9800000000000000, UL)
+#endif /* CONFIG_64BIT */
+
+#include <asm/mach-generic/spaces.h>
+#endif
diff --git a/arch/mips/include/asm/mach-malta/kernel-entry-init.h b/arch/mips/include/asm/mach-malta/kernel-entry-init.h
index 0b793e7bf67..77eeda77e73 100644
--- a/arch/mips/include/asm/mach-malta/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-malta/kernel-entry-init.h
@@ -5,27 +5,104 @@
*
* Chris Dearman (chris@mips.com)
* Copyright (C) 2007 Mips Technologies, Inc.
+ * Copyright (C) 2014 Imagination Technologies Ltd.
*/
#ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+ /*
+ * Prepare segments for EVA boot:
+ *
+ * This is in case the processor boots in legacy configuration
+ * (SI_EVAReset is de-asserted and CONFIG5.K == 0)
+ *
+ * On entry, t1 is loaded with CP0_CONFIG
+ *
+ * ========================= Mappings =============================
+ * Virtual memory Physical memory Mapping
+ * 0x00000000 - 0x7fffffff 0x80000000 - 0xfffffffff MUSUK (kuseg)
+ * Flat 2GB physical memory
+ *
+ * 0x80000000 - 0x9fffffff 0x00000000 - 0x1ffffffff MUSUK (kseg0)
+ * 0xa0000000 - 0xbf000000 0x00000000 - 0x1ffffffff MUSUK (kseg1)
+ * 0xc0000000 - 0xdfffffff - MK (kseg2)
+ * 0xe0000000 - 0xffffffff - MK (kseg3)
+ *
+ *
+ * Lowmem is expanded to 2GB
+ */
+ .macro eva_entry
+ /*
+ * Get Config.K0 value and use it to program
+ * the segmentation registers
+ */
+ andi t1, 0x7 /* CCA */
+ move t2, t1
+ ins t2, t1, 16, 3
+ /* SegCtl0 */
+ li t0, ((MIPS_SEGCFG_MK << MIPS_SEGCFG_AM_SHIFT) | \
+ (0 << MIPS_SEGCFG_PA_SHIFT) | \
+ (1 << MIPS_SEGCFG_EU_SHIFT)) | \
+ (((MIPS_SEGCFG_MK << MIPS_SEGCFG_AM_SHIFT) | \
+ (0 << MIPS_SEGCFG_PA_SHIFT) | \
+ (1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+ or t0, t2
+ mtc0 t0, $5, 2
+
+ /* SegCtl1 */
+ li t0, ((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) | \
+ (0 << MIPS_SEGCFG_PA_SHIFT) | \
+ (2 << MIPS_SEGCFG_C_SHIFT) | \
+ (1 << MIPS_SEGCFG_EU_SHIFT)) | \
+ (((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) | \
+ (0 << MIPS_SEGCFG_PA_SHIFT) | \
+ (1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+ ins t0, t1, 16, 3
+ mtc0 t0, $5, 3
+
+ /* SegCtl2 */
+ li t0, ((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) | \
+ (6 << MIPS_SEGCFG_PA_SHIFT) | \
+ (1 << MIPS_SEGCFG_EU_SHIFT)) | \
+ (((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) | \
+ (4 << MIPS_SEGCFG_PA_SHIFT) | \
+ (1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
+ or t0, t2
+ mtc0 t0, $5, 4
+
+ jal mips_ihb
+ mfc0 t0, $16, 5
+ li t2, 0x40000000 /* K bit */
+ or t0, t0, t2
+ mtc0 t0, $16, 5
+ sync
+ jal mips_ihb
+ .endm
+
.macro kernel_entry_setup
-#ifdef CONFIG_MIPS_MT_SMTC
- mfc0 t0, CP0_CONFIG
- bgez t0, 9f
+
+#ifdef CONFIG_EVA
+ sync
+ ehb
+
+ mfc0 t1, CP0_CONFIG
+ bgez t1, 9f
mfc0 t0, CP0_CONFIG, 1
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 2
bgez t0, 9f
mfc0 t0, CP0_CONFIG, 3
- and t0, 1<<2
- bnez t0, 0f
+ sll t0, t0, 6 /* SC bit */
+ bgez t0, 9f
+
+ eva_entry
+ b 0f
9:
/* Assume we came from YAMON... */
PTR_LA v0, 0x9fc00534 /* YAMON print */
lw v0, (v0)
move a0, zero
- PTR_LA a1, nonmt_processor
+ PTR_LA a1, nonsc_processor
jal v0
PTR_LA v0, 0x9fc00520 /* YAMON exit */
@@ -34,19 +111,25 @@
jal v0
1: b 1b
-
+ nop
__INITDATA
-nonmt_processor:
- .asciz "SMTC kernel requires the MT ASE to run\n"
+nonsc_processor:
+ .asciz "EVA kernel requires a MIPS core with Segment Control implemented\n"
__FINIT
+#endif /* CONFIG_EVA */
0:
-#endif
.endm
/*
* Do SMP slave processor setup necessary before we can safely execute C code.
*/
.macro smp_slave_setup
+#ifdef CONFIG_EVA
+ sync
+ ehb
+ mfc0 t1, CP0_CONFIG
+ eva_entry
+#endif
.endm
#endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/arch/mips/include/asm/mach-malta/malta-pm.h b/arch/mips/include/asm/mach-malta/malta-pm.h
new file mode 100644
index 00000000000..c2c2e201013
--- /dev/null
+++ b/arch/mips/include/asm/mach-malta/malta-pm.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MIPS_MACH_MALTA_PM_H__
+#define __ASM_MIPS_MACH_MALTA_PM_H__
+
+#include <asm/mips-boards/piix4.h>
+
+#ifdef CONFIG_MIPS_MALTA_PM
+
+/**
+ * mips_pm_suspend - enter a suspend state
+ * @state: the state to enter, one of PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_*
+ *
+ * Enters a suspend state via the Malta's PIIX4. If the state to be entered
+ * is one which loses context (eg. SOFF) then this function will never
+ * return.
+ */
+extern int mips_pm_suspend(unsigned state);
+
+#else /* !CONFIG_MIPS_MALTA_PM */
+
+static inline int mips_pm_suspend(unsigned state)
+{
+ return -EINVAL;
+}
+
+#endif /* !CONFIG_MIPS_MALTA_PM */
+
+#endif /* __ASM_MIPS_MACH_MALTA_PM_H__ */
diff --git a/arch/mips/include/asm/mach-malta/spaces.h b/arch/mips/include/asm/mach-malta/spaces.h
new file mode 100644
index 00000000000..d7e54971ec6
--- /dev/null
+++ b/arch/mips/include/asm/mach-malta/spaces.h
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ */
+
+#ifndef _ASM_MALTA_SPACES_H
+#define _ASM_MALTA_SPACES_H
+
+#ifdef CONFIG_EVA
+
+/*
+ * Traditional Malta Board Memory Map for EVA
+ *
+ * 0x00000000 - 0x0fffffff: 1st RAM region, 256MB
+ * 0x10000000 - 0x1bffffff: GIC and CPC Control Registers
+ * 0x1c000000 - 0x1fffffff: I/O And Flash
+ * 0x20000000 - 0x7fffffff: 2nd RAM region, 1.5GB
+ * 0x80000000 - 0xffffffff: Physical memory aliases to 0x0 (2GB)
+ *
+ * The kernel is still located in 0x80000000(kseg0). However,
+ * the physical mask has been shifted to 0x80000000 which exploits the alias
+ * on the Malta board. As a result of which, we override the __pa_symbol
+ * to peform direct mapping from virtual to physical addresses. In other
+ * words, the 0x80000000 virtual address maps to 0x80000000 physical address
+ * which in turn aliases to 0x0. We do this in order to be able to use a flat
+ * 2GB of memory (0x80000000 - 0xffffffff) so we can avoid the I/O hole in
+ * 0x10000000 - 0x1fffffff.
+ * The last 64KB of physical memory are reserved for correct HIGHMEM
+ * macros arithmetics.
+ *
+ */
+
+#define PAGE_OFFSET _AC(0x0, UL)
+#define PHYS_OFFSET _AC(0x80000000, UL)
+#define HIGHMEM_START _AC(0xffff0000, UL)
+
+#define __pa_symbol(x) (RELOC_HIDE((unsigned long)(x), 0))
+
+#endif /* CONFIG_EVA */
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* _ASM_MALTA_SPACES_H */
diff --git a/arch/mips/include/asm/mach-netlogic/irq.h b/arch/mips/include/asm/mach-netlogic/irq.h
index 868ed8a2ed5..c0dbd530cca 100644
--- a/arch/mips/include/asm/mach-netlogic/irq.h
+++ b/arch/mips/include/asm/mach-netlogic/irq.h
@@ -9,7 +9,8 @@
#define __ASM_NETLOGIC_IRQ_H
#include <asm/mach-netlogic/multi-node.h>
-#define NR_IRQS (64 * NLM_NR_NODES)
+#define NLM_IRQS_PER_NODE 1024
+#define NR_IRQS (NLM_IRQS_PER_NODE * NLM_NR_NODES)
#define MIPS_CPU_IRQ_BASE 0
diff --git a/arch/mips/include/asm/mach-netlogic/multi-node.h b/arch/mips/include/asm/mach-netlogic/multi-node.h
index d62fc773f4d..9ed8dacdc37 100644
--- a/arch/mips/include/asm/mach-netlogic/multi-node.h
+++ b/arch/mips/include/asm/mach-netlogic/multi-node.h
@@ -47,8 +47,37 @@
#endif
#endif
-#define NLM_CORES_PER_NODE 8
#define NLM_THREADS_PER_CORE 4
-#define NLM_CPUS_PER_NODE (NLM_CORES_PER_NODE * NLM_THREADS_PER_CORE)
+#ifdef CONFIG_CPU_XLR
+#define nlm_cores_per_node() 8
+#else
+extern unsigned int xlp_cores_per_node;
+#define nlm_cores_per_node() xlp_cores_per_node
+#endif
+
+#define nlm_threads_per_node() (nlm_cores_per_node() * NLM_THREADS_PER_CORE)
+#define nlm_cpuid_to_node(c) ((c) / nlm_threads_per_node())
+
+struct nlm_soc_info {
+ unsigned long coremask; /* cores enabled on the soc */
+ unsigned long ebase; /* not used now */
+ uint64_t irqmask; /* EIMR for the node */
+ uint64_t sysbase; /* only for XLP - sys block base */
+ uint64_t picbase; /* PIC block base */
+ spinlock_t piclock; /* lock for PIC access */
+ cpumask_t cpumask; /* logical cpu mask for node */
+ unsigned int socbus;
+};
+
+extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
+#define nlm_get_node(i) (&nlm_nodes[i])
+#define nlm_node_present(n) ((n) >= 0 && (n) < NLM_NR_NODES && \
+ nlm_get_node(n)->coremask != 0)
+#ifdef CONFIG_CPU_XLR
+#define nlm_current_node() (&nlm_nodes[0])
+#else
+#define nlm_current_node() (&nlm_nodes[nlm_nodeid()])
+#endif
+void nlm_node_init(int node);
#endif
diff --git a/arch/mips/include/asm/mach-netlogic/topology.h b/arch/mips/include/asm/mach-netlogic/topology.h
new file mode 100644
index 00000000000..ceeb1f5e712
--- /dev/null
+++ b/arch/mips/include/asm/mach-netlogic/topology.h
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Broadcom Corporation
+ */
+#ifndef _ASM_MACH_NETLOGIC_TOPOLOGY_H
+#define _ASM_MACH_NETLOGIC_TOPOLOGY_H
+
+#include <asm/mach-netlogic/multi-node.h>
+
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu) cpu_to_node(cpu)
+#define topology_core_id(cpu) (cpu_logical_map(cpu) / NLM_THREADS_PER_CORE)
+#define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu])
+#define topology_core_cpumask(cpu) cpumask_of_node(cpu_to_node(cpu))
+#endif
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_MACH_NETLOGIC_TOPOLOGY_H */
diff --git a/arch/mips/include/asm/mach-paravirt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-paravirt/cpu-feature-overrides.h
new file mode 100644
index 00000000000..725e1ed83f6
--- /dev/null
+++ b/arch/mips/include/asm/mach-paravirt/cpu-feature-overrides.h
@@ -0,0 +1,36 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc.
+ */
+#ifndef __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_tx39_cache 0
+#define cpu_has_counter 1
+#define cpu_has_llsc 1
+/*
+ * We Disable LL/SC on non SMP systems as it is faster to disable
+ * interrupts for atomic access than a LL/SC.
+ */
+#ifdef CONFIG_SMP
+# define kernel_uses_llsc 1
+#else
+# define kernel_uses_llsc 0
+#endif
+
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define cpu_dcache_line_size() 128
+#define cpu_icache_line_size() 128
+#define cpu_has_octeon_cache 1
+#define cpu_has_4k_cache 0
+#else
+#define cpu_has_octeon_cache 0
+#define cpu_has_4k_cache 1
+#endif
+
+#endif /* __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-paravirt/irq.h b/arch/mips/include/asm/mach-paravirt/irq.h
new file mode 100644
index 00000000000..9b4d35eca97
--- /dev/null
+++ b/arch/mips/include/asm/mach-paravirt/irq.h
@@ -0,0 +1,19 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc.
+ */
+#ifndef __ASM_MACH_PARAVIRT_IRQ_H__
+#define __ASM_MACH_PARAVIRT_IRQ_H__
+
+#define NR_IRQS 64
+#define MIPS_CPU_IRQ_BASE 1
+
+#define MIPS_IRQ_PCIA (MIPS_CPU_IRQ_BASE + 8)
+
+#define MIPS_IRQ_MBOX0 (MIPS_CPU_IRQ_BASE + 32)
+#define MIPS_IRQ_MBOX1 (MIPS_CPU_IRQ_BASE + 33)
+
+#endif /* __ASM_MACH_PARAVIRT_IRQ_H__ */
diff --git a/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h b/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h
new file mode 100644
index 00000000000..2f82bfa3a77
--- /dev/null
+++ b/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h
@@ -0,0 +1,50 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc
+ */
+#ifndef __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H
+#define __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H
+
+#define CP0_EBASE $15, 1
+
+ .macro kernel_entry_setup
+ mfc0 t0, CP0_EBASE
+ andi t0, t0, 0x3ff # CPUNum
+ beqz t0, 1f
+ # CPUs other than zero goto smp_bootstrap
+ j smp_bootstrap
+
+1:
+ .endm
+
+/*
+ * Do SMP slave processor setup necessary before we can safely execute
+ * C code.
+ */
+ .macro smp_slave_setup
+ mfc0 t0, CP0_EBASE
+ andi t0, t0, 0x3ff # CPUNum
+ slti t1, t0, NR_CPUS
+ bnez t1, 1f
+2:
+ di
+ wait
+ b 2b # Unknown CPU, loop forever.
+1:
+ PTR_LA t1, paravirt_smp_sp
+ PTR_SLL t0, PTR_SCALESHIFT
+ PTR_ADDU t1, t1, t0
+3:
+ PTR_L sp, 0(t1)
+ beqz sp, 3b # Spin until told to proceed.
+
+ PTR_LA t1, paravirt_smp_gp
+ PTR_ADDU t1, t1, t0
+ sync
+ PTR_L gp, 0(t1)
+ .endm
+
+#endif /* __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-powertv/war.h b/arch/mips/include/asm/mach-paravirt/war.h
index c5651c8e58d..36d3afb9845 100644
--- a/arch/mips/include/asm/mach-powertv/war.h
+++ b/arch/mips/include/asm/mach-paravirt/war.h
@@ -3,13 +3,11 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * This version for the PowerTV platform copied from the Malta version.
- *
* Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
- * Portions copyright (C) 2009 Cisco Systems, Inc.
+ * Copyright (C) 2013 Cavium Networks <support@caviumnetworks.com>
*/
-#ifndef __ASM_MACH_POWERTV_WAR_H
-#define __ASM_MACH_POWERTV_WAR_H
+#ifndef __ASM_MIPS_MACH_PARAVIRT_WAR_H
+#define __ASM_MIPS_MACH_PARAVIRT_WAR_H
#define R4600_V1_INDEX_ICACHEOP_WAR 0
#define R4600_V1_HIT_CACHEOP_WAR 0
@@ -17,11 +15,11 @@
#define R5432_CP0_INTERRUPT_WAR 0
#define BCM1250_M3_WAR 0
#define SIBYTE_1956_WAR 0
-#define MIPS4K_ICACHE_REFILL_WAR 1
-#define MIPS_CACHE_SYNC_WAR 1
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
-#define ICACHE_REFILLS_WORKAROUND_WAR 1
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
#define R10000_LLSC_WAR 0
#define MIPS34K_MISSED_ITLB_WAR 0
-#endif /* __ASM_MACH_POWERTV_WAR_H */
+#endif /* __ASM_MIPS_MACH_PARAVIRT_WAR_H */
diff --git a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
index 2dbc7a8cec1..fc946c83599 100644
--- a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
+++ b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
@@ -76,7 +76,7 @@ static inline void set_value_reg32(volatile u32 *const addr,
__asm__ __volatile__(
" .set push \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %0, %1 # set_value_reg32 \n"
" and %0, %2 \n"
" or %0, %3 \n"
@@ -98,7 +98,7 @@ static inline void set_reg32(volatile u32 *const addr,
__asm__ __volatile__(
" .set push \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %0, %1 # set_reg32 \n"
" or %0, %2 \n"
" sc %0, %1 \n"
@@ -119,7 +119,7 @@ static inline void clear_reg32(volatile u32 *const addr,
__asm__ __volatile__(
" .set push \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %0, %1 # clear_reg32 \n"
" and %0, %2 \n"
" sc %0, %1 \n"
@@ -140,7 +140,7 @@ static inline void toggle_reg32(volatile u32 *const addr,
__asm__ __volatile__(
" .set push \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
"1: ll %0, %1 # toggle_reg32 \n"
" xor %0, %2 \n"
" sc %0, %1 \n"
@@ -216,7 +216,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
#define custom_read_reg32(address, tmp) \
__asm__ __volatile__( \
" .set push \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
"1: ll %0, %1 #custom_read_reg32 \n" \
" .set pop \n" \
: "=r" (tmp), "=m" (*address) \
@@ -225,7 +225,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
#define custom_write_reg32(address, tmp) \
__asm__ __volatile__( \
" .set push \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
" sc %0, %1 #custom_write_reg32 \n" \
" "__beqz"%0, 1b \n" \
" nop \n" \
diff --git a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h
index aa45e6a0712..fe1566f2913 100644
--- a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h
+++ b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h
@@ -25,11 +25,7 @@
#ifndef MSP_USB_H_
#define MSP_USB_H_
-#ifdef CONFIG_MSP_HAS_DUAL_USB
-#define NUM_USB_DEVS 2
-#else
#define NUM_USB_DEVS 1
-#endif
/* Register spaces for USB host 0 */
#define MSP_USB0_MAB_START (MSP_USB0_BASE + 0x0)
diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h
deleted file mode 100644
index b341108d12f..00000000000
--- a/arch/mips/include/asm/mach-powertv/asic.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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 _ASM_MACH_POWERTV_ASIC_H
-#define _ASM_MACH_POWERTV_ASIC_H
-
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/mach-powertv/asic_regs.h>
-
-#define DVR_CAPABLE (1<<0)
-#define PCIE_CAPABLE (1<<1)
-#define FFS_CAPABLE (1<<2)
-#define DISPLAY_CAPABLE (1<<3)
-
-/* Platform Family types
- * For compitability, the new value must be added in the end */
-enum family_type {
- FAMILY_8500,
- FAMILY_8500RNG,
- FAMILY_4500,
- FAMILY_1500,
- FAMILY_8600,
- FAMILY_4600,
- FAMILY_4600VZA,
- FAMILY_8600VZB,
- FAMILY_1500VZE,
- FAMILY_1500VZF,
- FAMILY_8700,
- FAMILIES
-};
-
-/* Register maps for each ASIC */
-extern const struct register_map calliope_register_map;
-extern const struct register_map cronus_register_map;
-extern const struct register_map gaia_register_map;
-extern const struct register_map zeus_register_map;
-
-extern struct resource dvr_cronus_resources[];
-extern struct resource dvr_gaia_resources[];
-extern struct resource dvr_zeus_resources[];
-extern struct resource non_dvr_calliope_resources[];
-extern struct resource non_dvr_cronus_resources[];
-extern struct resource non_dvr_cronuslite_resources[];
-extern struct resource non_dvr_gaia_resources[];
-extern struct resource non_dvr_vz_calliope_resources[];
-extern struct resource non_dvr_vze_calliope_resources[];
-extern struct resource non_dvr_vzf_calliope_resources[];
-extern struct resource non_dvr_zeus_resources[];
-
-extern void powertv_platform_init(void);
-extern void platform_alloc_bootmem(void);
-extern enum asic_type platform_get_asic(void);
-extern enum family_type platform_get_family(void);
-extern int platform_supports_dvr(void);
-extern int platform_supports_ffs(void);
-extern int platform_supports_pcie(void);
-extern int platform_supports_display(void);
-extern void configure_platform(void);
-
-/* Platform Resources */
-#define ASIC_RESOURCE_GET_EXISTS 1
-extern struct resource *asic_resource_get(const char *name);
-extern void platform_release_memory(void *baddr, int size);
-
-/* USB configuration */
-struct usb_hcd; /* Forward reference */
-extern void platform_configure_usb_ehci(void);
-extern void platform_unconfigure_usb_ehci(void);
-extern void platform_configure_usb_ohci(void);
-extern void platform_unconfigure_usb_ohci(void);
-
-/* Resource for ASIC registers */
-extern struct resource asic_resource;
-extern int platform_usb_devices_init(struct platform_device **echi_dev,
- struct platform_device **ohci_dev);
-
-/* Reboot Cause */
-extern void set_reboot_cause(char code, unsigned int data, unsigned int data2);
-extern void set_locked_reboot_cause(char code, unsigned int data,
- unsigned int data2);
-
-enum sys_reboot_type {
- sys_unknown_reboot = 0x00, /* Unknown reboot cause */
- sys_davic_change = 0x01, /* Reboot due to change in DAVIC
- * mode */
- sys_user_reboot = 0x02, /* Reboot initiated by user */
- sys_system_reboot = 0x03, /* Reboot initiated by OS */
- sys_trap_reboot = 0x04, /* Reboot due to a CPU trap */
- sys_silent_reboot = 0x05, /* Silent reboot */
- sys_boot_ldr_reboot = 0x06, /* Bootloader reboot */
- sys_power_up_reboot = 0x07, /* Power on bootup. Older
- * drivers may report as
- * userReboot. */
- sys_code_change = 0x08, /* Reboot to take code change.
- * Older drivers may report as
- * userReboot. */
- sys_hardware_reset = 0x09, /* HW watchdog or front-panel
- * reset button reset. Older
- * drivers may report as
- * userReboot. */
- sys_watchdogInterrupt = 0x0A /* Pre-watchdog interrupt */
-};
-
-#endif /* _ASM_MACH_POWERTV_ASIC_H */
diff --git a/arch/mips/include/asm/mach-powertv/asic_reg_map.h b/arch/mips/include/asm/mach-powertv/asic_reg_map.h
deleted file mode 100644
index 20348e817b0..00000000000
--- a/arch/mips/include/asm/mach-powertv/asic_reg_map.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * asic_reg_map.h
- *
- * A macro-enclosed list of the elements for the register_map structure for
- * use in defining and manipulating the structure.
- *
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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
- */
-
-REGISTER_MAP_ELEMENT(eic_slow0_strt_add)
-REGISTER_MAP_ELEMENT(eic_cfg_bits)
-REGISTER_MAP_ELEMENT(eic_ready_status)
-REGISTER_MAP_ELEMENT(chipver3)
-REGISTER_MAP_ELEMENT(chipver2)
-REGISTER_MAP_ELEMENT(chipver1)
-REGISTER_MAP_ELEMENT(chipver0)
-REGISTER_MAP_ELEMENT(uart1_intstat)
-REGISTER_MAP_ELEMENT(uart1_inten)
-REGISTER_MAP_ELEMENT(uart1_config1)
-REGISTER_MAP_ELEMENT(uart1_config2)
-REGISTER_MAP_ELEMENT(uart1_divisorhi)
-REGISTER_MAP_ELEMENT(uart1_divisorlo)
-REGISTER_MAP_ELEMENT(uart1_data)
-REGISTER_MAP_ELEMENT(uart1_status)
-REGISTER_MAP_ELEMENT(int_stat_3)
-REGISTER_MAP_ELEMENT(int_stat_2)
-REGISTER_MAP_ELEMENT(int_stat_1)
-REGISTER_MAP_ELEMENT(int_stat_0)
-REGISTER_MAP_ELEMENT(int_config)
-REGISTER_MAP_ELEMENT(int_int_scan)
-REGISTER_MAP_ELEMENT(ien_int_3)
-REGISTER_MAP_ELEMENT(ien_int_2)
-REGISTER_MAP_ELEMENT(ien_int_1)
-REGISTER_MAP_ELEMENT(ien_int_0)
-REGISTER_MAP_ELEMENT(int_level_3_3)
-REGISTER_MAP_ELEMENT(int_level_3_2)
-REGISTER_MAP_ELEMENT(int_level_3_1)
-REGISTER_MAP_ELEMENT(int_level_3_0)
-REGISTER_MAP_ELEMENT(int_level_2_3)
-REGISTER_MAP_ELEMENT(int_level_2_2)
-REGISTER_MAP_ELEMENT(int_level_2_1)
-REGISTER_MAP_ELEMENT(int_level_2_0)
-REGISTER_MAP_ELEMENT(int_level_1_3)
-REGISTER_MAP_ELEMENT(int_level_1_2)
-REGISTER_MAP_ELEMENT(int_level_1_1)
-REGISTER_MAP_ELEMENT(int_level_1_0)
-REGISTER_MAP_ELEMENT(int_level_0_3)
-REGISTER_MAP_ELEMENT(int_level_0_2)
-REGISTER_MAP_ELEMENT(int_level_0_1)
-REGISTER_MAP_ELEMENT(int_level_0_0)
-REGISTER_MAP_ELEMENT(int_docsis_en)
-REGISTER_MAP_ELEMENT(mips_pll_setup)
-REGISTER_MAP_ELEMENT(fs432x4b4_usb_ctl)
-REGISTER_MAP_ELEMENT(test_bus)
-REGISTER_MAP_ELEMENT(crt_spare)
-REGISTER_MAP_ELEMENT(usb2_ohci_int_mask)
-REGISTER_MAP_ELEMENT(usb2_strap)
-REGISTER_MAP_ELEMENT(ehci_hcapbase)
-REGISTER_MAP_ELEMENT(ohci_hc_revision)
-REGISTER_MAP_ELEMENT(bcm1_bs_lmi_steer)
-REGISTER_MAP_ELEMENT(usb2_control)
-REGISTER_MAP_ELEMENT(usb2_stbus_obc)
-REGISTER_MAP_ELEMENT(usb2_stbus_mess_size)
-REGISTER_MAP_ELEMENT(usb2_stbus_chunk_size)
-REGISTER_MAP_ELEMENT(pcie_regs)
-REGISTER_MAP_ELEMENT(tim_ch)
-REGISTER_MAP_ELEMENT(tim_cl)
-REGISTER_MAP_ELEMENT(gpio_dout)
-REGISTER_MAP_ELEMENT(gpio_din)
-REGISTER_MAP_ELEMENT(gpio_dir)
-REGISTER_MAP_ELEMENT(watchdog)
-REGISTER_MAP_ELEMENT(front_panel)
-REGISTER_MAP_ELEMENT(misc_clk_ctl1)
-REGISTER_MAP_ELEMENT(misc_clk_ctl2)
-REGISTER_MAP_ELEMENT(crt_ext_ctl)
-REGISTER_MAP_ELEMENT(register_maps)
diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h
deleted file mode 100644
index 06712abb3e5..00000000000
--- a/arch/mips/include/asm/mach-powertv/asic_regs.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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 __ASM_MACH_POWERTV_ASIC_H_
-#define __ASM_MACH_POWERTV_ASIC_H_
-#include <linux/io.h>
-
-/* ASIC types */
-enum asic_type {
- ASIC_UNKNOWN,
- ASIC_ZEUS,
- ASIC_CALLIOPE,
- ASIC_CRONUS,
- ASIC_CRONUSLITE,
- ASIC_GAIA,
- ASICS /* Number of supported ASICs */
-};
-
-/* hardcoded values read from Chip Version registers */
-#define CRONUS_10 0x0B4C1C20
-#define CRONUS_11 0x0B4C1C21
-#define CRONUSLITE_10 0x0B4C1C40
-
-#define NAND_FLASH_BASE 0x03000000
-#define CALLIOPE_IO_BASE 0x08000000
-#define GAIA_IO_BASE 0x09000000
-#define CRONUS_IO_BASE 0x09000000
-#define ZEUS_IO_BASE 0x09000000
-
-#define ASIC_IO_SIZE 0x01000000
-
-/* Definitions for backward compatibility */
-#define UART1_INTSTAT uart1_intstat
-#define UART1_INTEN uart1_inten
-#define UART1_CONFIG1 uart1_config1
-#define UART1_CONFIG2 uart1_config2
-#define UART1_DIVISORHI uart1_divisorhi
-#define UART1_DIVISORLO uart1_divisorlo
-#define UART1_DATA uart1_data
-#define UART1_STATUS uart1_status
-
-/* ASIC register enumeration */
-union register_map_entry {
- unsigned long phys;
- u32 *virt;
-};
-
-#define REGISTER_MAP_ELEMENT(x) union register_map_entry x;
-struct register_map {
-#include <asm/mach-powertv/asic_reg_map.h>
-};
-#undef REGISTER_MAP_ELEMENT
-
-/**
- * register_map_offset_phys - add an offset to the physical address
- * @map: Pointer to the &struct register_map
- * @offset: Value to add
- *
- * Only adds the base to non-zero physical addresses
- */
-static inline void register_map_offset_phys(struct register_map *map,
- unsigned long offset)
-{
-#define REGISTER_MAP_ELEMENT(x) do { \
- if (map->x.phys != 0) \
- map->x.phys += offset; \
- } while (false);
-
-#include <asm/mach-powertv/asic_reg_map.h>
-#undef REGISTER_MAP_ELEMENT
-}
-
-/**
- * register_map_virtualize - Convert &register_map to virtual addresses
- * @map: Pointer to &register_map to virtualize
- */
-static inline void register_map_virtualize(struct register_map *map)
-{
-#define REGISTER_MAP_ELEMENT(x) do { \
- map->x.virt = (!map->x.phys) ? NULL : \
- UNCAC_ADDR(phys_to_virt(map->x.phys)); \
- } while (false);
-
-#include <asm/mach-powertv/asic_reg_map.h>
-#undef REGISTER_MAP_ELEMENT
-}
-
-extern struct register_map _asic_register_map;
-extern unsigned long asic_phy_base;
-
-/*
- * Macros to interface to registers through their ioremapped address
- * asic_reg_phys_addr Returns the physical address of the given register
- * asic_reg_addr Returns the iomapped virtual address of the given
- * register.
- */
-#define asic_reg_addr(x) (_asic_register_map.x.virt)
-#define asic_reg_phys_addr(x) (virt_to_phys((void *) CAC_ADDR( \
- (unsigned long) asic_reg_addr(x))))
-
-/*
- * The asic_reg macro is gone. It should be replaced by either asic_read or
- * asic_write, as appropriate.
- */
-
-#define asic_read(x) readl(asic_reg_addr(x))
-#define asic_write(v, x) writel(v, asic_reg_addr(x))
-
-extern void asic_irq_init(void);
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
deleted file mode 100644
index 58c76ec32a1..00000000000
--- a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010 Cisco Systems, 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.
- *
- * 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 _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
-#define _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
-#define cpu_has_tlb 1
-#define cpu_has_4kex 1
-#define cpu_has_3k_cache 0
-#define cpu_has_4k_cache 1
-#define cpu_has_tx39_cache 0
-#define cpu_has_fpu 0
-#define cpu_has_counter 1
-#define cpu_has_watch 1
-#define cpu_has_divec 1
-#define cpu_has_vce 0
-#define cpu_has_cache_cdex_p 0
-#define cpu_has_cache_cdex_s 0
-#define cpu_has_mcheck 1
-#define cpu_has_ejtag 1
-#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_vtag_icache 0
-#define cpu_has_dc_aliases 0
-#define cpu_has_ic_fills_f_dc 0
-#define cpu_has_mips32r1 0
-#define cpu_has_mips32r2 1
-#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_has_nofpuex 0
-#define cpu_has_64bits 0
-#define cpu_has_64bit_zero_reg 0
-#define cpu_has_vint 1
-#define cpu_has_veic 1
-#define cpu_has_inclusive_pcaches 0
-
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
deleted file mode 100644
index f8316720a21..00000000000
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ /dev/null
@@ -1,117 +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.
- *
- * Version from mach-generic modified to support PowerTV port
- * Portions Copyright (C) 2009 Cisco Systems, Inc.
- * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org>
- *
- */
-
-#ifndef __ASM_MACH_POWERTV_DMA_COHERENCE_H
-#define __ASM_MACH_POWERTV_DMA_COHERENCE_H
-
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <asm/mach-powertv/asic.h>
-
-static inline bool is_kseg2(void *addr)
-{
- return (unsigned long)addr >= KSEG2;
-}
-
-static inline unsigned long virt_to_phys_from_pte(void *addr)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- unsigned long virt_addr = (unsigned long)addr;
- unsigned long phys_addr = 0UL;
-
- /* get the page global directory. */
- pgd = pgd_offset_k(virt_addr);
-
- if (!pgd_none(*pgd)) {
- /* get the page upper directory */
- pud = pud_offset(pgd, virt_addr);
- if (!pud_none(*pud)) {
- /* get the page middle directory */
- pmd = pmd_offset(pud, virt_addr);
- if (!pmd_none(*pmd)) {
- /* get a pointer to the page table entry */
- ptep = pte_offset(pmd, virt_addr);
- pte = *ptep;
- /* check for a valid page */
- if (pte_present(pte)) {
- /* get the physical address the page is
- * referring to */
- phys_addr = (unsigned long)
- page_to_phys(pte_page(pte));
- /* add the offset within the page */
- phys_addr |= (virt_addr & ~PAGE_MASK);
- }
- }
- }
- }
-
- return phys_addr;
-}
-
-static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
- size_t size)
-{
- if (is_kseg2(addr))
- return phys_to_dma(virt_to_phys_from_pte(addr));
- else
- return phys_to_dma(virt_to_phys(addr));
-}
-
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
- struct page *page)
-{
- return phys_to_dma(page_to_phys(page));
-}
-
-static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
- dma_addr_t dma_addr)
-{
- return dma_to_phys(dma_addr);
-}
-
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction)
-{
-}
-
-static inline int plat_dma_supported(struct device *dev, u64 mask)
-{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- */
- if (mask < DMA_BIT_MASK(24))
- return 0;
-
- return 1;
-}
-
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
-static inline int plat_device_is_coherent(struct device *dev)
-{
- return 0;
-}
-
-#endif /* __ASM_MACH_POWERTV_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-powertv/interrupts.h b/arch/mips/include/asm/mach-powertv/interrupts.h
deleted file mode 100644
index 6c463be6215..00000000000
--- a/arch/mips/include/asm/mach-powertv/interrupts.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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 _ASM_MACH_POWERTV_INTERRUPTS_H_
-#define _ASM_MACH_POWERTV_INTERRUPTS_H_
-
-/*
- * Defines for all of the interrupt lines
- */
-
-/* Definitions for backward compatibility */
-#define kIrq_Uart1 irq_uart1
-
-#define ibase 0
-
-/*------------- Register: int_stat_3 */
-/* 126 unused (bit 31) */
-#define irq_asc2video (ibase+126) /* ASC 2 Video Interrupt */
-#define irq_asc1video (ibase+125) /* ASC 1 Video Interrupt */
-#define irq_comms_block_wd (ibase+124) /* ASC 1 Video Interrupt */
-#define irq_fdma_mailbox (ibase+123) /* FDMA Mailbox Output */
-#define irq_fdma_gp (ibase+122) /* FDMA GP Output */
-#define irq_mips_pic (ibase+121) /* MIPS Performance Counter
- * Interrupt */
-#define irq_mips_timer (ibase+120) /* MIPS Timer Interrupt */
-#define irq_memory_protect (ibase+119) /* Memory Protection Interrupt
- * -- Ored by glue logic inside
- * SPARC ILC (see
- * INT_MEM_PROT_STAT, below,
- * for individual interrupts)
- */
-/* 118 unused (bit 22) */
-#define irq_sbag (ibase+117) /* SBAG Interrupt -- Ored by
- * glue logic inside SPARC ILC
- * (see INT_SBAG_STAT, below,
- * for individual interrupts) */
-#define irq_qam_b_fec (ibase+116) /* QAM B FEC Interrupt */
-#define irq_qam_a_fec (ibase+115) /* QAM A FEC Interrupt */
-/* 114 unused (bit 18) */
-#define irq_mailbox (ibase+113) /* Mailbox Debug Interrupt --
- * Ored by glue logic inside
- * SPARC ILC (see
- * INT_MAILBOX_STAT, below, for
- * individual interrupts) */
-#define irq_fuse_stat1 (ibase+112) /* Fuse Status 1 */
-#define irq_fuse_stat2 (ibase+111) /* Fuse Status 2 */
-#define irq_fuse_stat3 (ibase+110) /* Blitter Interrupt / Fuse
- * Status 3 */
-#define irq_blitter (ibase+110) /* Blitter Interrupt / Fuse
- * Status 3 */
-#define irq_avc1_pp0 (ibase+109) /* AVC Decoder #1 PP0
- * Interrupt */
-#define irq_avc1_pp1 (ibase+108) /* AVC Decoder #1 PP1
- * Interrupt */
-#define irq_avc1_mbe (ibase+107) /* AVC Decoder #1 MBE
- * Interrupt */
-#define irq_avc2_pp0 (ibase+106) /* AVC Decoder #2 PP0
- * Interrupt */
-#define irq_avc2_pp1 (ibase+105) /* AVC Decoder #2 PP1
- * Interrupt */
-#define irq_avc2_mbe (ibase+104) /* AVC Decoder #2 MBE
- * Interrupt */
-#define irq_zbug_spi (ibase+103) /* Zbug SPI Slave Interrupt */
-#define irq_qam_mod2 (ibase+102) /* QAM Modulator 2 DMA
- * Interrupt */
-#define irq_ir_rx (ibase+101) /* IR RX 2 Interrupt */
-#define irq_aud_dsp2 (ibase+100) /* Audio DSP #2 Interrupt */
-#define irq_aud_dsp1 (ibase+99) /* Audio DSP #1 Interrupt */
-#define irq_docsis (ibase+98) /* DOCSIS Debug Interrupt */
-#define irq_sd_dvp1 (ibase+97) /* SD DVP #1 Interrupt */
-#define irq_sd_dvp2 (ibase+96) /* SD DVP #2 Interrupt */
-/*------------- Register: int_stat_2 */
-#define irq_hd_dvp (ibase+95) /* HD DVP Interrupt */
-#define kIrq_Prewatchdog (ibase+94) /* watchdog Pre-Interrupt */
-#define irq_timer2 (ibase+93) /* Programmable Timer
- * Interrupt 2 */
-#define irq_1394 (ibase+92) /* 1394 Firewire Interrupt */
-#define irq_usbohci (ibase+91) /* USB 2.0 OHCI Interrupt */
-#define irq_usbehci (ibase+90) /* USB 2.0 EHCI Interrupt */
-#define irq_pciexp (ibase+89) /* PCI Express 0 Interrupt */
-#define irq_pciexp0 (ibase+89) /* PCI Express 0 Interrupt */
-#define irq_afe1 (ibase+88) /* AFE 1 Interrupt */
-#define irq_sata (ibase+87) /* SATA 1 Interrupt */
-#define irq_sata1 (ibase+87) /* SATA 1 Interrupt */
-#define irq_dtcp (ibase+86) /* DTCP Interrupt */
-#define irq_pciexp1 (ibase+85) /* PCI Express 1 Interrupt */
-/* 84 unused (bit 20) */
-/* 83 unused (bit 19) */
-/* 82 unused (bit 18) */
-#define irq_sata2 (ibase+81) /* SATA2 Interrupt */
-#define irq_uart2 (ibase+80) /* UART2 Interrupt */
-#define irq_legacy_usb (ibase+79) /* Legacy USB Host ISR (1.1
- * Host module) */
-#define irq_pod (ibase+78) /* POD Interrupt */
-#define irq_slave_usb (ibase+77) /* Slave USB */
-#define irq_denc1 (ibase+76) /* DENC #1 VTG Interrupt */
-#define irq_vbi_vtg (ibase+75) /* VBI VTG Interrupt */
-#define irq_afe2 (ibase+74) /* AFE 2 Interrupt */
-#define irq_denc2 (ibase+73) /* DENC #2 VTG Interrupt */
-#define irq_asc2 (ibase+72) /* ASC #2 Interrupt */
-#define irq_asc1 (ibase+71) /* ASC #1 Interrupt */
-#define irq_mod_dma (ibase+70) /* Modulator DMA Interrupt */
-#define irq_byte_eng1 (ibase+69) /* Byte Engine Interrupt [1] */
-#define irq_byte_eng0 (ibase+68) /* Byte Engine Interrupt [0] */
-/* 67 unused (bit 03) */
-/* 66 unused (bit 02) */
-/* 65 unused (bit 01) */
-/* 64 unused (bit 00) */
-/*------------- Register: int_stat_1 */
-/* 63 unused (bit 31) */
-/* 62 unused (bit 30) */
-/* 61 unused (bit 29) */
-/* 60 unused (bit 28) */
-/* 59 unused (bit 27) */
-/* 58 unused (bit 26) */
-/* 57 unused (bit 25) */
-/* 56 unused (bit 24) */
-#define irq_buf_dma_mem2mem (ibase+55) /* BufDMA Memory to Memory
- * Interrupt */
-#define irq_buf_dma_usbtransmit (ibase+54) /* BufDMA USB Transmit
- * Interrupt */
-#define irq_buf_dma_qpskpodtransmit (ibase+53) /* BufDMA QPSK/POD Tramsit
- * Interrupt */
-#define irq_buf_dma_transmit_error (ibase+52) /* BufDMA Transmit Error
- * Interrupt */
-#define irq_buf_dma_usbrecv (ibase+51) /* BufDMA USB Receive
- * Interrupt */
-#define irq_buf_dma_qpskpodrecv (ibase+50) /* BufDMA QPSK/POD Receive
- * Interrupt */
-#define irq_buf_dma_recv_error (ibase+49) /* BufDMA Receive Error
- * Interrupt */
-#define irq_qamdma_transmit_play (ibase+48) /* QAMDMA Transmit/Play
- * Interrupt */
-#define irq_qamdma_transmit_error (ibase+47) /* QAMDMA Transmit Error
- * Interrupt */
-#define irq_qamdma_recv2high (ibase+46) /* QAMDMA Receive 2 High
- * (Chans 63-32) */
-#define irq_qamdma_recv2low (ibase+45) /* QAMDMA Receive 2 Low
- * (Chans 31-0) */
-#define irq_qamdma_recv1high (ibase+44) /* QAMDMA Receive 1 High
- * (Chans 63-32) */
-#define irq_qamdma_recv1low (ibase+43) /* QAMDMA Receive 1 Low
- * (Chans 31-0) */
-#define irq_qamdma_recv_error (ibase+42) /* QAMDMA Receive Error
- * Interrupt */
-#define irq_mpegsplice (ibase+41) /* MPEG Splice Interrupt */
-#define irq_deinterlace_rdy (ibase+40) /* Deinterlacer Frame Ready
- * Interrupt */
-#define irq_ext_in0 (ibase+39) /* External Interrupt irq_in0 */
-#define irq_gpio3 (ibase+38) /* GP I/O IRQ 3 - From GP I/O
- * Module */
-#define irq_gpio2 (ibase+37) /* GP I/O IRQ 2 - From GP I/O
- * Module (ABE_intN) */
-#define irq_pcrcmplt1 (ibase+36) /* PCR Capture Complete or
- * Discontinuity 1 */
-#define irq_pcrcmplt2 (ibase+35) /* PCR Capture Complete or
- * Discontinuity 2 */
-#define irq_parse_peierr (ibase+34) /* PID Parser Error Detect
- * (PEI) */
-#define irq_parse_cont_err (ibase+33) /* PID Parser continuity error
- * detect */
-#define irq_ds1framer (ibase+32) /* DS1 Framer Interrupt */
-/*------------- Register: int_stat_0 */
-#define irq_gpio1 (ibase+31) /* GP I/O IRQ 1 - From GP I/O
- * Module */
-#define irq_gpio0 (ibase+30) /* GP I/O IRQ 0 - From GP I/O
- * Module */
-#define irq_qpsk_out_aloha (ibase+29) /* QPSK Output Slotted Aloha
- * (chan 3) Transmission
- * Completed OK */
-#define irq_qpsk_out_tdma (ibase+28) /* QPSK Output TDMA (chan 2)
- * Transmission Completed OK */
-#define irq_qpsk_out_reserve (ibase+27) /* QPSK Output Reservation
- * (chan 1) Transmission
- * Completed OK */
-#define irq_qpsk_out_aloha_err (ibase+26) /* QPSK Output Slotted Aloha
- * (chan 3)Transmission
- * completed with Errors. */
-#define irq_qpsk_out_tdma_err (ibase+25) /* QPSK Output TDMA (chan 2)
- * Transmission completed with
- * Errors. */
-#define irq_qpsk_out_rsrv_err (ibase+24) /* QPSK Output Reservation
- * (chan 1) Transmission
- * completed with Errors */
-#define irq_aloha_fail (ibase+23) /* Unsuccessful Resend of Aloha
- * for N times. Aloha retry
- * timeout for channel 3. */
-#define irq_timer1 (ibase+22) /* Programmable Timer
- * Interrupt */
-#define irq_keyboard (ibase+21) /* Keyboard Module Interrupt */
-#define irq_i2c (ibase+20) /* I2C Module Interrupt */
-#define irq_spi (ibase+19) /* SPI Module Interrupt */
-#define irq_irblaster (ibase+18) /* IR Blaster Interrupt */
-#define irq_splice_detect (ibase+17) /* PID Key Change Interrupt or
- * Splice Detect Interrupt */
-#define irq_se_micro (ibase+16) /* Secure Micro I/F Module
- * Interrupt */
-#define irq_uart1 (ibase+15) /* UART Interrupt */
-#define irq_irrecv (ibase+14) /* IR Receiver Interrupt */
-#define irq_host_int1 (ibase+13) /* Host-to-Host Interrupt 1 */
-#define irq_host_int0 (ibase+12) /* Host-to-Host Interrupt 0 */
-#define irq_qpsk_hecerr (ibase+11) /* QPSK HEC Error Interrupt */
-#define irq_qpsk_crcerr (ibase+10) /* QPSK AAL-5 CRC Error
- * Interrupt */
-/* 9 unused (bit 09) */
-/* 8 unused (bit 08) */
-#define irq_psicrcerr (ibase+7) /* QAM PSI CRC Error
- * Interrupt */
-#define irq_psilength_err (ibase+6) /* QAM PSI Length Error
- * Interrupt */
-#define irq_esfforward (ibase+5) /* ESF Interrupt Mark From
- * Forward Path Reference -
- * every 3ms when forward Mbits
- * and forward slot control
- * bytes are updated. */
-#define irq_esfreverse (ibase+4) /* ESF Interrupt Mark from
- * Reverse Path Reference -
- * delayed from forward mark by
- * the ranging delay plus a
- * fixed amount. When reverse
- * Mbits and reverse slot
- * control bytes are updated.
- * Occurs every 3ms for 3.0M and
- * 1.554 M upstream rates and
- * every 6 ms for 256K upstream
- * rate. */
-#define irq_aloha_timeout (ibase+3) /* Slotted-Aloha timeout on
- * Channel 1. */
-#define irq_reservation (ibase+2) /* Partial (or Incremental)
- * Reservation Message Completed
- * or Slotted aloha verify for
- * channel 1. */
-#define irq_aloha3 (ibase+1) /* Slotted-Aloha Message Verify
- * Interrupt or Reservation
- * increment completed for
- * channel 3. */
-#define irq_mpeg_d (ibase+0) /* MPEG Decoder Interrupt */
-#endif /* _ASM_MACH_POWERTV_INTERRUPTS_H_ */
diff --git a/arch/mips/include/asm/mach-powertv/ioremap.h b/arch/mips/include/asm/mach-powertv/ioremap.h
deleted file mode 100644
index c86ef094ec3..00000000000
--- a/arch/mips/include/asm/mach-powertv/ioremap.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.
- *
- * Portions Copyright (C) Cisco Systems, Inc.
- */
-#ifndef __ASM_MACH_POWERTV_IOREMAP_H
-#define __ASM_MACH_POWERTV_IOREMAP_H
-
-#include <linux/types.h>
-#include <linux/log2.h>
-#include <linux/compiler.h>
-
-#include <asm/pgtable-bits.h>
-#include <asm/addrspace.h>
-
-/* We're going to mess with bits, so get sizes */
-#define IOR_BPC 8 /* Bits per char */
-#define IOR_PHYS_BITS (IOR_BPC * sizeof(phys_addr_t))
-#define IOR_DMA_BITS (IOR_BPC * sizeof(dma_addr_t))
-
-/*
- * Define the granularity of physical/DMA mapping in terms of the number
- * of bits that defines the offset within a grain. These will be the
- * least significant bits of the address. The rest of a physical or DMA
- * address will be used to index into an appropriate table to find the
- * offset to add to the address to yield the corresponding DMA or physical
- * address, respectively.
- */
-#define IOR_LSBITS 22 /* Bits in a grain */
-
-/*
- * Compute the number of most significant address bits after removing those
- * used for the offset within a grain and then compute the number of table
- * entries for the conversion.
- */
-#define IOR_PHYS_MSBITS (IOR_PHYS_BITS - IOR_LSBITS)
-#define IOR_NUM_PHYS_TO_DMA ((phys_addr_t) 1 << IOR_PHYS_MSBITS)
-
-#define IOR_DMA_MSBITS (IOR_DMA_BITS - IOR_LSBITS)
-#define IOR_NUM_DMA_TO_PHYS ((dma_addr_t) 1 << IOR_DMA_MSBITS)
-
-/*
- * Define data structures used as elements in the arrays for the conversion
- * between physical and DMA addresses. We do some slightly fancy math to
- * compute the width of the offset element of the conversion tables so
- * that we can have the smallest conversion tables. Next, round up the
- * sizes to the next higher power of two, i.e. the offset element will have
- * 8, 16, 32, 64, etc. bits. This eliminates the need to mask off any
- * bits. Finally, we compute a shift value that puts the most significant
- * bits of the offset into the most significant bits of the offset element.
- * This makes it more efficient on processors without barrel shifters and
- * easier to see the values if the conversion table is dumped in binary.
- */
-#define _IOR_OFFSET_WIDTH(n) (1 << order_base_2(n))
-#define IOR_OFFSET_WIDTH(n) \
- (_IOR_OFFSET_WIDTH(n) < 8 ? 8 : _IOR_OFFSET_WIDTH(n))
-
-#define IOR_PHYS_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_PHYS_MSBITS)
-#define IOR_PHYS_SHIFT (IOR_PHYS_BITS - IOR_PHYS_OFFSET_BITS)
-
-#define IOR_DMA_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_DMA_MSBITS)
-#define IOR_DMA_SHIFT (IOR_DMA_BITS - IOR_DMA_OFFSET_BITS)
-
-struct ior_phys_to_dma {
- dma_addr_t offset:IOR_DMA_OFFSET_BITS __packed
- __aligned((IOR_DMA_OFFSET_BITS / IOR_BPC));
-};
-
-struct ior_dma_to_phys {
- dma_addr_t offset:IOR_PHYS_OFFSET_BITS __packed
- __aligned((IOR_PHYS_OFFSET_BITS / IOR_BPC));
-};
-
-extern struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
-extern struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];
-
-static inline dma_addr_t _phys_to_dma_offset_raw(phys_addr_t phys)
-{
- return (dma_addr_t)_ior_phys_to_dma[phys >> IOR_LSBITS].offset;
-}
-
-static inline dma_addr_t _dma_to_phys_offset_raw(dma_addr_t dma)
-{
- return (dma_addr_t)_ior_dma_to_phys[dma >> IOR_LSBITS].offset;
-}
-
-/* These are not portable and should not be used in drivers. Drivers should
- * be using ioremap() and friends to map physical addresses to virtual
- * addresses and dma_map*() and friends to map virtual addresses into DMA
- * addresses and back.
- */
-static inline dma_addr_t phys_to_dma(phys_addr_t phys)
-{
- return phys + (_phys_to_dma_offset_raw(phys) << IOR_PHYS_SHIFT);
-}
-
-static inline phys_addr_t dma_to_phys(dma_addr_t dma)
-{
- return dma + (_dma_to_phys_offset_raw(dma) << IOR_DMA_SHIFT);
-}
-
-extern void ioremap_add_map(dma_addr_t phys, phys_addr_t alias,
- dma_addr_t size);
-
-/*
- * Allow physical addresses to be fixed up to help peripherals located
- * outside the low 32-bit range -- generic pass-through version.
- */
-static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
-{
- return phys_addr;
-}
-
-/*
- * Handle the special case of addresses the area aliased into the first
- * 512 MiB of the processor's physical address space. These turn into either
- * kseg0 or kseg1 addresses, depending on flags.
- */
-static inline void __iomem *plat_ioremap(phys_t start, unsigned long size,
- unsigned long flags)
-{
- phys_addr_t start_offset;
- void __iomem *result = NULL;
-
- /* Start by checking to see whether this is an aliased address */
- start_offset = _dma_to_phys_offset_raw(start);
-
- /*
- * If:
- * o the memory is aliased into the first 512 MiB, and
- * o the start and end are in the same RAM bank, and
- * o we don't have a zero size or wrap around, and
- * o we are supposed to create an uncached mapping,
- * handle this is a kseg0 or kseg1 address
- */
- if (start_offset != 0) {
- phys_addr_t last;
- dma_addr_t dma_to_phys_offset;
-
- last = start + size - 1;
- dma_to_phys_offset =
- _dma_to_phys_offset_raw(last) << IOR_DMA_SHIFT;
-
- if (dma_to_phys_offset == start_offset &&
- size != 0 && start <= last) {
- phys_t adjusted_start;
- adjusted_start = start + start_offset;
- if (flags == _CACHE_UNCACHED)
- result = (void __iomem *) (unsigned long)
- CKSEG1ADDR(adjusted_start);
- else
- result = (void __iomem *) (unsigned long)
- CKSEG0ADDR(adjusted_start);
- }
- }
-
- return result;
-}
-
-static inline int plat_iounmap(const volatile void __iomem *addr)
-{
- return 0;
-}
-#endif /* __ASM_MACH_POWERTV_IOREMAP_H */
diff --git a/arch/mips/include/asm/mach-powertv/irq.h b/arch/mips/include/asm/mach-powertv/irq.h
deleted file mode 100644
index 4bd5d0c61a9..00000000000
--- a/arch/mips/include/asm/mach-powertv/irq.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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 _ASM_MACH_POWERTV_IRQ_H
-#define _ASM_MACH_POWERTV_IRQ_H
-#include <asm/mach-powertv/interrupts.h>
-
-#define MIPS_CPU_IRQ_BASE ibase
-#define NR_IRQS 127
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/powertv-clock.h b/arch/mips/include/asm/mach-powertv/powertv-clock.h
deleted file mode 100644
index 6f3e9a0fcf8..00000000000
--- a/arch/mips/include/asm/mach-powertv/powertv-clock.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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
- */
-/*
- * Local definitions for the powertv PCI code
- */
-
-#ifndef _POWERTV_PCI_POWERTV_PCI_H_
-#define _POWERTV_PCI_POWERTV_PCI_H_
-extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-extern int asic_pcie_init(void);
-extern int asic_pcie_init(void);
-
-extern int log_level;
-#endif
diff --git a/arch/mips/include/asm/mach-ralink/war.h b/arch/mips/include/asm/mach-ralink/war.h
index a7b712cf2d2..c074b5dc1f8 100644
--- a/arch/mips/include/asm/mach-ralink/war.h
+++ b/arch/mips/include/asm/mach-ralink/war.h
@@ -17,7 +17,6 @@
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
-#define RM9000_CDEX_SMP_WAR 0
#define ICACHE_REFILLS_WORKAROUND_WAR 0
#define R10000_LLSC_WAR 0
#define MIPS34K_MISSED_ITLB_WAR 0
diff --git a/arch/mips/include/asm/mach-sead3/kernel-entry-init.h b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h
index 3dfbd8e7947..6cccd4d558d 100644
--- a/arch/mips/include/asm/mach-sead3/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h
@@ -10,37 +10,6 @@
#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
.macro kernel_entry_setup
-#ifdef CONFIG_MIPS_MT_SMTC
- mfc0 t0, CP0_CONFIG
- bgez t0, 9f
- mfc0 t0, CP0_CONFIG, 1
- bgez t0, 9f
- mfc0 t0, CP0_CONFIG, 2
- bgez t0, 9f
- mfc0 t0, CP0_CONFIG, 3
- and t0, 1<<2
- bnez t0, 0f
-9 :
- /* Assume we came from YAMON... */
- PTR_LA v0, 0x9fc00534 /* YAMON print */
- lw v0, (v0)
- move a0, zero
- PTR_LA a1, nonmt_processor
- jal v0
-
- PTR_LA v0, 0x9fc00520 /* YAMON exit */
- lw v0, (v0)
- li a0, 1
- jal v0
-
-1 : b 1b
-
- __INITDATA
-nonmt_processor :
- .asciz "SMTC kernel requires the MT ASE to run\n"
- __FINIT
-0 :
-#endif
.endm
/*
diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h
index 48616816bcb..c904c24550f 100644
--- a/arch/mips/include/asm/mips-boards/generic.h
+++ b/arch/mips/include/asm/mips-boards/generic.h
@@ -67,10 +67,6 @@
extern int mips_revision_sconid;
-#ifdef CONFIG_OF
-extern struct boot_param_header __dtb_start;
-#endif
-
#ifdef CONFIG_PCI
extern void mips_pcibios_init(void);
#else
diff --git a/arch/mips/include/asm/mips-boards/malta.h b/arch/mips/include/asm/mips-boards/malta.h
index 722bc889eab..fd9774269a5 100644
--- a/arch/mips/include/asm/mips-boards/malta.h
+++ b/arch/mips/include/asm/mips-boards/malta.h
@@ -64,6 +64,11 @@ static inline unsigned long get_msc_port_base(unsigned long reg)
#define GIC_ADDRSPACE_SZ (128 * 1024)
/*
+ * CPC Specific definitions
+ */
+#define CPC_BASE_ADDR 0x1bde0000
+
+/*
* MSC01 BIU Specific definitions
* FIXME : These should be elsewhere ?
*/
diff --git a/arch/mips/include/asm/mips-boards/piix4.h b/arch/mips/include/asm/mips-boards/piix4.h
index a02596cf1ab..9e340be52a5 100644
--- a/arch/mips/include/asm/mips-boards/piix4.h
+++ b/arch/mips/include/asm/mips-boards/piix4.h
@@ -1,6 +1,7 @@
/*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
@@ -20,61 +21,50 @@
#ifndef __ASM_MIPS_BOARDS_PIIX4_H
#define __ASM_MIPS_BOARDS_PIIX4_H
-/************************************************************************
- * IO register offsets
- ************************************************************************/
-#define PIIX4_ICTLR1_ICW1 0x20
-#define PIIX4_ICTLR1_ICW2 0x21
-#define PIIX4_ICTLR1_ICW3 0x21
-#define PIIX4_ICTLR1_ICW4 0x21
-#define PIIX4_ICTLR2_ICW1 0xa0
-#define PIIX4_ICTLR2_ICW2 0xa1
-#define PIIX4_ICTLR2_ICW3 0xa1
-#define PIIX4_ICTLR2_ICW4 0xa1
-#define PIIX4_ICTLR1_OCW1 0x21
-#define PIIX4_ICTLR1_OCW2 0x20
-#define PIIX4_ICTLR1_OCW3 0x20
-#define PIIX4_ICTLR1_OCW4 0x20
-#define PIIX4_ICTLR2_OCW1 0xa1
-#define PIIX4_ICTLR2_OCW2 0xa0
-#define PIIX4_ICTLR2_OCW3 0xa0
-#define PIIX4_ICTLR2_OCW4 0xa0
+/* PIRQX Route Control */
+#define PIIX4_FUNC0_PIRQRC 0x60
+#define PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_DISABLE (1 << 7)
+#define PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MASK 0xf
+#define PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX 16
+/* SERIRQ Control */
+#define PIIX4_FUNC0_SERIRQC 0x64
+#define PIIX4_FUNC0_SERIRQC_EN (1 << 7)
+#define PIIX4_FUNC0_SERIRQC_CONT (1 << 6)
+/* Top Of Memory */
+#define PIIX4_FUNC0_TOM 0x69
+#define PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK 0xf0
+/* Deterministic Latency Control */
+#define PIIX4_FUNC0_DLC 0x82
+#define PIIX4_FUNC0_DLC_USBPR_EN (1 << 2)
+#define PIIX4_FUNC0_DLC_PASSIVE_RELEASE_EN (1 << 1)
+#define PIIX4_FUNC0_DLC_DELAYED_TRANSACTION_EN (1 << 0)
+/* General Configuration */
+#define PIIX4_FUNC0_GENCFG 0xb0
+#define PIIX4_FUNC0_GENCFG_SERIRQ (1 << 16)
+/* IDE Timing */
+#define PIIX4_FUNC1_IDETIM_PRIMARY_LO 0x40
+#define PIIX4_FUNC1_IDETIM_PRIMARY_HI 0x41
+#define PIIX4_FUNC1_IDETIM_PRIMARY_HI_IDE_DECODE_EN (1 << 7)
+#define PIIX4_FUNC1_IDETIM_SECONDARY_LO 0x42
+#define PIIX4_FUNC1_IDETIM_SECONDARY_HI 0x43
+#define PIIX4_FUNC1_IDETIM_SECONDARY_HI_IDE_DECODE_EN (1 << 7)
-/************************************************************************
- * Register encodings.
- ************************************************************************/
-#define PIIX4_OCW2_NSEOI (0x1 << 5)
-#define PIIX4_OCW2_SEOI (0x3 << 5)
-#define PIIX4_OCW2_RNSEOI (0x5 << 5)
-#define PIIX4_OCW2_RAEOIS (0x4 << 5)
-#define PIIX4_OCW2_RAEOIC (0x0 << 5)
-#define PIIX4_OCW2_RSEOI (0x7 << 5)
-#define PIIX4_OCW2_SP (0x6 << 5)
-#define PIIX4_OCW2_NOP (0x2 << 5)
+/* Power Management Configuration Space */
+#define PIIX4_FUNC3_PMBA 0x40
+#define PIIX4_FUNC3_PMREGMISC 0x80
+#define PIIX4_FUNC3_PMREGMISC_EN (1 << 0)
-#define PIIX4_OCW2_SEL (0x0 << 3)
+/* Power Management IO Space */
+#define PIIX4_FUNC3IO_PMSTS 0x00
+#define PIIX4_FUNC3IO_PMSTS_PWRBTN_STS (1 << 8)
+#define PIIX4_FUNC3IO_PMCNTRL 0x04
+#define PIIX4_FUNC3IO_PMCNTRL_SUS_EN (1 << 13)
+#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP (0x7 << 10)
+#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF (0x0 << 10)
+#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_STR (0x1 << 10)
-#define PIIX4_OCW2_ILS_0 0
-#define PIIX4_OCW2_ILS_1 1
-#define PIIX4_OCW2_ILS_2 2
-#define PIIX4_OCW2_ILS_3 3
-#define PIIX4_OCW2_ILS_4 4
-#define PIIX4_OCW2_ILS_5 5
-#define PIIX4_OCW2_ILS_6 6
-#define PIIX4_OCW2_ILS_7 7
-#define PIIX4_OCW2_ILS_8 0
-#define PIIX4_OCW2_ILS_9 1
-#define PIIX4_OCW2_ILS_10 2
-#define PIIX4_OCW2_ILS_11 3
-#define PIIX4_OCW2_ILS_12 4
-#define PIIX4_OCW2_ILS_13 5
-#define PIIX4_OCW2_ILS_14 6
-#define PIIX4_OCW2_ILS_15 7
-
-#define PIIX4_OCW3_SEL (0x1 << 3)
-
-#define PIIX4_OCW3_IRR 0x2
-#define PIIX4_OCW3_ISR 0x3
+/* Data for magic special PCI cycle */
+#define PIIX4_SUSPEND_MAGIC 0x00120002
#endif /* __ASM_MIPS_BOARDS_PIIX4_H */
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
new file mode 100644
index 00000000000..6a9d2dd005c
--- /dev/null
+++ b/arch/mips/include/asm/mips-cm.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_MIPS_CM_H__
+#define __MIPS_ASM_MIPS_CM_H__
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+/* The base address of the CM GCR block */
+extern void __iomem *mips_cm_base;
+
+/* The base address of the CM L2-only sync region */
+extern void __iomem *mips_cm_l2sync_base;
+
+/**
+ * __mips_cm_phys_base - retrieve the physical base address of the CM
+ *
+ * This function returns the physical base address of the Coherence Manager
+ * global control block, or 0 if no Coherence Manager is present. It provides
+ * a default implementation which reads the CMGCRBase register where available,
+ * and may be overriden by platforms which determine this address in a
+ * different way by defining a function with the same prototype except for the
+ * name mips_cm_phys_base (without underscores).
+ */
+extern phys_t __mips_cm_phys_base(void);
+
+/**
+ * mips_cm_probe - probe for a Coherence Manager
+ *
+ * Attempt to detect the presence of a Coherence Manager. Returns 0 if a CM
+ * is successfully detected, else -errno.
+ */
+#ifdef CONFIG_MIPS_CM
+extern int mips_cm_probe(void);
+#else
+static inline int mips_cm_probe(void)
+{
+ return -ENODEV;
+}
+#endif
+
+/**
+ * mips_cm_present - determine whether a Coherence Manager is present
+ *
+ * Returns true if a CM is present in the system, else false.
+ */
+static inline bool mips_cm_present(void)
+{
+#ifdef CONFIG_MIPS_CM
+ return mips_cm_base != NULL;
+#else
+ return false;
+#endif
+}
+
+/**
+ * mips_cm_has_l2sync - determine whether an L2-only sync region is present
+ *
+ * Returns true if the system implements an L2-only sync region, else false.
+ */
+static inline bool mips_cm_has_l2sync(void)
+{
+#ifdef CONFIG_MIPS_CM
+ return mips_cm_l2sync_base != NULL;
+#else
+ return false;
+#endif
+}
+
+/* Offsets to register blocks from the CM base address */
+#define MIPS_CM_GCB_OFS 0x0000 /* Global Control Block */
+#define MIPS_CM_CLCB_OFS 0x2000 /* Core Local Control Block */
+#define MIPS_CM_COCB_OFS 0x4000 /* Core Other Control Block */
+#define MIPS_CM_GDB_OFS 0x6000 /* Global Debug Block */
+
+/* Total size of the CM memory mapped registers */
+#define MIPS_CM_GCR_SIZE 0x8000
+
+/* Size of the L2-only sync region */
+#define MIPS_CM_L2SYNC_SIZE 0x1000
+
+/* Macros to ease the creation of register access functions */
+#define BUILD_CM_R_(name, off) \
+static inline u32 *addr_gcr_##name(void) \
+{ \
+ return (u32 *)(mips_cm_base + (off)); \
+} \
+ \
+static inline u32 read_gcr_##name(void) \
+{ \
+ return __raw_readl(addr_gcr_##name()); \
+}
+
+#define BUILD_CM__W(name, off) \
+static inline void write_gcr_##name(u32 value) \
+{ \
+ __raw_writel(value, addr_gcr_##name()); \
+}
+
+#define BUILD_CM_RW(name, off) \
+ BUILD_CM_R_(name, off) \
+ BUILD_CM__W(name, off)
+
+#define BUILD_CM_Cx_R_(name, off) \
+ BUILD_CM_R_(cl_##name, MIPS_CM_CLCB_OFS + (off)) \
+ BUILD_CM_R_(co_##name, MIPS_CM_COCB_OFS + (off))
+
+#define BUILD_CM_Cx__W(name, off) \
+ BUILD_CM__W(cl_##name, MIPS_CM_CLCB_OFS + (off)) \
+ BUILD_CM__W(co_##name, MIPS_CM_COCB_OFS + (off))
+
+#define BUILD_CM_Cx_RW(name, off) \
+ BUILD_CM_Cx_R_(name, off) \
+ BUILD_CM_Cx__W(name, off)
+
+/* GCB register accessor functions */
+BUILD_CM_R_(config, MIPS_CM_GCB_OFS + 0x00)
+BUILD_CM_RW(base, MIPS_CM_GCB_OFS + 0x08)
+BUILD_CM_RW(access, MIPS_CM_GCB_OFS + 0x20)
+BUILD_CM_R_(rev, MIPS_CM_GCB_OFS + 0x30)
+BUILD_CM_RW(error_mask, MIPS_CM_GCB_OFS + 0x40)
+BUILD_CM_RW(error_cause, MIPS_CM_GCB_OFS + 0x48)
+BUILD_CM_RW(error_addr, MIPS_CM_GCB_OFS + 0x50)
+BUILD_CM_RW(error_mult, MIPS_CM_GCB_OFS + 0x58)
+BUILD_CM_RW(l2_only_sync_base, MIPS_CM_GCB_OFS + 0x70)
+BUILD_CM_RW(gic_base, MIPS_CM_GCB_OFS + 0x80)
+BUILD_CM_RW(cpc_base, MIPS_CM_GCB_OFS + 0x88)
+BUILD_CM_RW(reg0_base, MIPS_CM_GCB_OFS + 0x90)
+BUILD_CM_RW(reg0_mask, MIPS_CM_GCB_OFS + 0x98)
+BUILD_CM_RW(reg1_base, MIPS_CM_GCB_OFS + 0xa0)
+BUILD_CM_RW(reg1_mask, MIPS_CM_GCB_OFS + 0xa8)
+BUILD_CM_RW(reg2_base, MIPS_CM_GCB_OFS + 0xb0)
+BUILD_CM_RW(reg2_mask, MIPS_CM_GCB_OFS + 0xb8)
+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)
+
+/* Core Local & Core Other register accessor functions */
+BUILD_CM_Cx_RW(reset_release, 0x00)
+BUILD_CM_Cx_RW(coherence, 0x08)
+BUILD_CM_Cx_R_(config, 0x10)
+BUILD_CM_Cx_RW(other, 0x18)
+BUILD_CM_Cx_RW(reset_base, 0x20)
+BUILD_CM_Cx_R_(id, 0x28)
+BUILD_CM_Cx_RW(reset_ext_base, 0x30)
+BUILD_CM_Cx_R_(tcid_0_priority, 0x40)
+BUILD_CM_Cx_R_(tcid_1_priority, 0x48)
+BUILD_CM_Cx_R_(tcid_2_priority, 0x50)
+BUILD_CM_Cx_R_(tcid_3_priority, 0x58)
+BUILD_CM_Cx_R_(tcid_4_priority, 0x60)
+BUILD_CM_Cx_R_(tcid_5_priority, 0x68)
+BUILD_CM_Cx_R_(tcid_6_priority, 0x70)
+BUILD_CM_Cx_R_(tcid_7_priority, 0x78)
+BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
+
+/* GCR_CONFIG register fields */
+#define CM_GCR_CONFIG_NUMIOCU_SHF 8
+#define CM_GCR_CONFIG_NUMIOCU_MSK (_ULCAST_(0xf) << 8)
+#define CM_GCR_CONFIG_PCORES_SHF 0
+#define CM_GCR_CONFIG_PCORES_MSK (_ULCAST_(0xff) << 0)
+
+/* GCR_BASE register fields */
+#define CM_GCR_BASE_GCRBASE_SHF 15
+#define CM_GCR_BASE_GCRBASE_MSK (_ULCAST_(0x1ffff) << 15)
+#define CM_GCR_BASE_CMDEFTGT_SHF 0
+#define CM_GCR_BASE_CMDEFTGT_MSK (_ULCAST_(0x3) << 0)
+#define CM_GCR_BASE_CMDEFTGT_DISABLED 0
+#define CM_GCR_BASE_CMDEFTGT_MEM 1
+#define CM_GCR_BASE_CMDEFTGT_IOCU0 2
+#define CM_GCR_BASE_CMDEFTGT_IOCU1 3
+
+/* GCR_ACCESS register fields */
+#define CM_GCR_ACCESS_ACCESSEN_SHF 0
+#define CM_GCR_ACCESS_ACCESSEN_MSK (_ULCAST_(0xff) << 0)
+
+/* GCR_REV register fields */
+#define CM_GCR_REV_MAJOR_SHF 8
+#define CM_GCR_REV_MAJOR_MSK (_ULCAST_(0xff) << 8)
+#define CM_GCR_REV_MINOR_SHF 0
+#define CM_GCR_REV_MINOR_MSK (_ULCAST_(0xff) << 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 CM_GCR_ERROR_CAUSE_ERRINFO_SHF 0
+#define CM_GCR_ERROR_CAUSE_ERRINGO_MSK (_ULCAST_(0x7ffffff) << 0)
+
+/* GCR_ERROR_MULT register fields */
+#define CM_GCR_ERROR_MULT_ERR2ND_SHF 0
+#define CM_GCR_ERROR_MULT_ERR2ND_MSK (_ULCAST_(0x1f) << 0)
+
+/* GCR_L2_ONLY_SYNC_BASE register fields */
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_SHF 12
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK (_ULCAST_(0xfffff) << 12)
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_SHF 0
+#define CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK (_ULCAST_(0x1) << 0)
+
+/* GCR_GIC_BASE register fields */
+#define CM_GCR_GIC_BASE_GICBASE_SHF 17
+#define CM_GCR_GIC_BASE_GICBASE_MSK (_ULCAST_(0x7fff) << 17)
+#define CM_GCR_GIC_BASE_GICEN_SHF 0
+#define CM_GCR_GIC_BASE_GICEN_MSK (_ULCAST_(0x1) << 0)
+
+/* GCR_CPC_BASE register fields */
+#define CM_GCR_CPC_BASE_CPCBASE_SHF 17
+#define CM_GCR_CPC_BASE_CPCBASE_MSK (_ULCAST_(0x7fff) << 17)
+#define CM_GCR_CPC_BASE_CPCEN_SHF 0
+#define CM_GCR_CPC_BASE_CPCEN_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)
+
+/* GCR_REGn_MASK register fields */
+#define CM_GCR_REGn_MASK_ADDRMASK_SHF 16
+#define CM_GCR_REGn_MASK_ADDRMASK_MSK (_ULCAST_(0xffff) << 16)
+#define CM_GCR_REGn_MASK_CCAOVR_SHF 5
+#define CM_GCR_REGn_MASK_CCAOVR_MSK (_ULCAST_(0x3) << 5)
+#define CM_GCR_REGn_MASK_CCAOVREN_SHF 4
+#define CM_GCR_REGn_MASK_CCAOVREN_MSK (_ULCAST_(0x1) << 4)
+#define CM_GCR_REGn_MASK_DROPL2_SHF 2
+#define CM_GCR_REGn_MASK_DROPL2_MSK (_ULCAST_(0x1) << 2)
+#define CM_GCR_REGn_MASK_CMTGT_SHF 0
+#define CM_GCR_REGn_MASK_CMTGT_MSK (_ULCAST_(0x3) << 0)
+#define CM_GCR_REGn_MASK_CMTGT_DISABLED (_ULCAST_(0x0) << 0)
+#define CM_GCR_REGn_MASK_CMTGT_MEM (_ULCAST_(0x1) << 0)
+#define CM_GCR_REGn_MASK_CMTGT_IOCU0 (_ULCAST_(0x2) << 0)
+#define CM_GCR_REGn_MASK_CMTGT_IOCU1 (_ULCAST_(0x3) << 0)
+
+/* GCR_GIC_STATUS register fields */
+#define CM_GCR_GIC_STATUS_EX_SHF 0
+#define CM_GCR_GIC_STATUS_EX_MSK (_ULCAST_(0x1) << 0)
+
+/* GCR_CPC_STATUS register fields */
+#define CM_GCR_CPC_STATUS_EX_SHF 0
+#define CM_GCR_CPC_STATUS_EX_MSK (_ULCAST_(0x1) << 0)
+
+/* GCR_Cx_COHERENCE register fields */
+#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF 0
+#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK (_ULCAST_(0xff) << 0)
+
+/* GCR_Cx_CONFIG register fields */
+#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)
+
+/* GCR_Cx_OTHER register fields */
+#define CM_GCR_Cx_OTHER_CORENUM_SHF 16
+#define CM_GCR_Cx_OTHER_CORENUM_MSK (_ULCAST_(0xffff) << 16)
+
+/* GCR_Cx_RESET_BASE register fields */
+#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_SHF 12
+#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_MSK (_ULCAST_(0xfffff) << 12)
+
+/* GCR_Cx_RESET_EXT_BASE register fields */
+#define CM_GCR_Cx_RESET_EXT_BASE_EVARESET_SHF 31
+#define CM_GCR_Cx_RESET_EXT_BASE_EVARESET_MSK (_ULCAST_(0x1) << 31)
+#define CM_GCR_Cx_RESET_EXT_BASE_UEB_SHF 30
+#define CM_GCR_Cx_RESET_EXT_BASE_UEB_MSK (_ULCAST_(0x1) << 30)
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCMASK_SHF 20
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCMASK_MSK (_ULCAST_(0xff) << 20)
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCPA_SHF 1
+#define CM_GCR_Cx_RESET_EXT_BASE_BEVEXCPA_MSK (_ULCAST_(0x7f) << 1)
+#define CM_GCR_Cx_RESET_EXT_BASE_PRESENT_SHF 0
+#define CM_GCR_Cx_RESET_EXT_BASE_PRESENT_MSK (_ULCAST_(0x1) << 0)
+
+/**
+ * mips_cm_numcores - return the number of cores present in the system
+ *
+ * Returns the value of the PCORES field of the GCR_CONFIG register plus 1, or
+ * zero if no Coherence Manager is present.
+ */
+static inline unsigned mips_cm_numcores(void)
+{
+ if (!mips_cm_present())
+ return 0;
+
+ return ((read_gcr_config() & CM_GCR_CONFIG_PCORES_MSK)
+ >> CM_GCR_CONFIG_PCORES_SHF) + 1;
+}
+
+/**
+ * mips_cm_numiocu - return the number of IOCUs present in the system
+ *
+ * Returns the value of the NUMIOCU field of the GCR_CONFIG register, or zero
+ * if no Coherence Manager is present.
+ */
+static inline unsigned mips_cm_numiocu(void)
+{
+ if (!mips_cm_present())
+ return 0;
+
+ return (read_gcr_config() & CM_GCR_CONFIG_NUMIOCU_MSK)
+ >> CM_GCR_CONFIG_NUMIOCU_SHF;
+}
+
+/**
+ * mips_cm_l2sync - perform an L2-only sync operation
+ *
+ * If an L2-only sync region is present in the system then this function
+ * performs and L2-only sync and returns zero. Otherwise it returns -ENODEV.
+ */
+static inline int mips_cm_l2sync(void)
+{
+ if (!mips_cm_has_l2sync())
+ return -ENODEV;
+
+ writel(0, mips_cm_l2sync_base);
+ return 0;
+}
+
+#endif /* __MIPS_ASM_MIPS_CM_H__ */
diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h
new file mode 100644
index 00000000000..e139a534e0f
--- /dev/null
+++ b/arch/mips/include/asm/mips-cpc.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_MIPS_CPC_H__
+#define __MIPS_ASM_MIPS_CPC_H__
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+/* The base address of the CPC registers */
+extern void __iomem *mips_cpc_base;
+
+/**
+ * mips_cpc_default_phys_base - retrieve the default physical base address of
+ * the CPC
+ *
+ * Returns the default physical base address of the Cluster Power Controller
+ * memory mapped registers. This is platform dependant & must therefore be
+ * implemented per-platform.
+ */
+extern phys_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_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
+ * a CPC is successfully detected, else -errno.
+ */
+#ifdef CONFIG_MIPS_CPC
+extern int mips_cpc_probe(void);
+#else
+static inline int mips_cpc_probe(void)
+{
+ return -ENODEV;
+}
+#endif
+
+/**
+ * mips_cpc_present - determine whether a Cluster Power Controller is present
+ *
+ * Returns true if a CPC is present in the system, else false.
+ */
+static inline bool mips_cpc_present(void)
+{
+#ifdef CONFIG_MIPS_CPC
+ return mips_cpc_base != NULL;
+#else
+ return false;
+#endif
+}
+
+/* Offsets from the CPC base address to various control blocks */
+#define MIPS_CPC_GCB_OFS 0x0000
+#define MIPS_CPC_CLCB_OFS 0x2000
+#define MIPS_CPC_COCB_OFS 0x4000
+
+/* Macros to ease the creation of register access functions */
+#define BUILD_CPC_R_(name, off) \
+static inline u32 *addr_cpc_##name(void) \
+{ \
+ return (u32 *)(mips_cpc_base + (off)); \
+} \
+ \
+static inline u32 read_cpc_##name(void) \
+{ \
+ return __raw_readl(mips_cpc_base + (off)); \
+}
+
+#define BUILD_CPC__W(name, off) \
+static inline void write_cpc_##name(u32 value) \
+{ \
+ __raw_writel(value, mips_cpc_base + (off)); \
+}
+
+#define BUILD_CPC_RW(name, off) \
+ BUILD_CPC_R_(name, off) \
+ BUILD_CPC__W(name, off)
+
+#define BUILD_CPC_Cx_R_(name, off) \
+ BUILD_CPC_R_(cl_##name, MIPS_CPC_CLCB_OFS + (off)) \
+ BUILD_CPC_R_(co_##name, MIPS_CPC_COCB_OFS + (off))
+
+#define BUILD_CPC_Cx__W(name, off) \
+ BUILD_CPC__W(cl_##name, MIPS_CPC_CLCB_OFS + (off)) \
+ BUILD_CPC__W(co_##name, MIPS_CPC_COCB_OFS + (off))
+
+#define BUILD_CPC_Cx_RW(name, off) \
+ BUILD_CPC_Cx_R_(name, off) \
+ BUILD_CPC_Cx__W(name, off)
+
+/* GCB register accessor functions */
+BUILD_CPC_RW(access, MIPS_CPC_GCB_OFS + 0x00)
+BUILD_CPC_RW(seqdel, MIPS_CPC_GCB_OFS + 0x08)
+BUILD_CPC_RW(rail, MIPS_CPC_GCB_OFS + 0x10)
+BUILD_CPC_RW(resetlen, MIPS_CPC_GCB_OFS + 0x18)
+BUILD_CPC_R_(revision, MIPS_CPC_GCB_OFS + 0x20)
+
+/* Core Local & Core Other accessor functions */
+BUILD_CPC_Cx_RW(cmd, 0x00)
+BUILD_CPC_Cx_RW(stat_conf, 0x08)
+BUILD_CPC_Cx_RW(other, 0x10)
+
+/* CPC_Cx_CMD register fields */
+#define CPC_Cx_CMD_SHF 0
+#define CPC_Cx_CMD_MSK (_ULCAST_(0xf) << 0)
+#define CPC_Cx_CMD_CLOCKOFF (_ULCAST_(0x1) << 0)
+#define CPC_Cx_CMD_PWRDOWN (_ULCAST_(0x2) << 0)
+#define CPC_Cx_CMD_PWRUP (_ULCAST_(0x3) << 0)
+#define CPC_Cx_CMD_RESET (_ULCAST_(0x4) << 0)
+
+/* CPC_Cx_STAT_CONF register fields */
+#define CPC_Cx_STAT_CONF_PWRUPE_SHF 23
+#define CPC_Cx_STAT_CONF_PWRUPE_MSK (_ULCAST_(0x1) << 23)
+#define CPC_Cx_STAT_CONF_SEQSTATE_SHF 19
+#define CPC_Cx_STAT_CONF_SEQSTATE_MSK (_ULCAST_(0xf) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_D0 (_ULCAST_(0x0) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_U0 (_ULCAST_(0x1) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_U1 (_ULCAST_(0x2) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_U2 (_ULCAST_(0x3) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_U3 (_ULCAST_(0x4) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_U4 (_ULCAST_(0x5) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_U5 (_ULCAST_(0x6) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_U6 (_ULCAST_(0x7) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_D1 (_ULCAST_(0x8) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_D3 (_ULCAST_(0x9) << 19)
+#define CPC_Cx_STAT_CONF_SEQSTATE_D2 (_ULCAST_(0xa) << 19)
+#define CPC_Cx_STAT_CONF_CLKGAT_IMPL_SHF 17
+#define CPC_Cx_STAT_CONF_CLKGAT_IMPL_MSK (_ULCAST_(0x1) << 17)
+#define CPC_Cx_STAT_CONF_PWRDN_IMPL_SHF 16
+#define CPC_Cx_STAT_CONF_PWRDN_IMPL_MSK (_ULCAST_(0x1) << 16)
+#define CPC_Cx_STAT_CONF_EJTAG_PROBE_SHF 15
+#define CPC_Cx_STAT_CONF_EJTAG_PROBE_MSK (_ULCAST_(0x1) << 15)
+
+/* CPC_Cx_OTHER register fields */
+#define CPC_Cx_OTHER_CORENUM_SHF 16
+#define CPC_Cx_OTHER_CORENUM_MSK (_ULCAST_(0xff) << 16)
+
+#ifdef CONFIG_MIPS_CPC
+
+/**
+ * mips_cpc_lock_other - lock access to another core
+ * 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
+ * by a call to mips_cpc_unlock_other.
+ */
+extern void mips_cpc_lock_other(unsigned int core);
+
+/**
+ * mips_cpc_unlock_other - unlock access to another core
+ *
+ * Call after operating upon another core via the 'other' register region.
+ * Must be called after mips_cpc_lock_other.
+ */
+extern void mips_cpc_unlock_other(void);
+
+#else /* !CONFIG_MIPS_CPC */
+
+static inline void mips_cpc_lock_other(unsigned int core) { }
+static inline void mips_cpc_unlock_other(void) { }
+
+#endif /* !CONFIG_MIPS_CPC */
+
+#endif /* __MIPS_ASM_MIPS_CPC_H__ */
diff --git a/arch/mips/include/asm/mips_mt.h b/arch/mips/include/asm/mips_mt.h
index ac7935203f8..f6ba004a771 100644
--- a/arch/mips/include/asm/mips_mt.h
+++ b/arch/mips/include/asm/mips_mt.h
@@ -1,7 +1,6 @@
/*
- * Definitions and decalrations for MIPS MT support
- * that are common between SMTC, VSMP, and/or AP/SP
- * kernel models.
+ * Definitions and decalrations for MIPS MT support that are common between
+ * the VSMP, and AP/SP kernel models.
*/
#ifndef __ASM_MIPS_MT_H
#define __ASM_MIPS_MT_H
@@ -18,7 +17,12 @@ extern cpumask_t mt_fpu_cpumask;
extern unsigned long mt_fpemul_threshold;
extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
+
+#ifdef CONFIG_MIPS_MT
extern void mips_mt_set_cpuoptions(void);
+#else
+static inline void mips_mt_set_cpuoptions(void) { }
+#endif
struct class;
extern struct class *mt_class;
diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h
index 38b7704ee37..5f8052ce43b 100644
--- a/arch/mips/include/asm/mipsmtregs.h
+++ b/arch/mips/include/asm/mipsmtregs.h
@@ -36,6 +36,8 @@
#define read_c0_tcbind() __read_32bit_c0_register($2, 2)
+#define write_c0_tchalt(val) __write_32bit_c0_register($2, 4, val)
+
#define read_c0_tccontext() __read_32bit_c0_register($2, 5)
#define write_c0_tccontext(val) __write_32bit_c0_register($2, 5, val)
@@ -176,6 +178,17 @@
#ifndef __ASSEMBLY__
+static inline unsigned core_nvpes(void)
+{
+ unsigned conf0;
+
+ if (!cpu_has_mipsmt)
+ return 1;
+
+ conf0 = read_c0_mvpconf0();
+ return ((conf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+}
+
static inline unsigned int dvpe(void)
{
int res = 0;
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index fed1c3e9b48..98e9754a4b6 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -14,6 +14,7 @@
#define _ASM_MIPSREGS_H
#include <linux/linkage.h>
+#include <linux/types.h>
#include <asm/hazards.h>
#include <asm/war.h>
@@ -567,13 +568,27 @@
#define MIPS_CONF1_PC (_ULCAST_(1) << 4)
#define MIPS_CONF1_MD (_ULCAST_(1) << 5)
#define MIPS_CONF1_C2 (_ULCAST_(1) << 6)
+#define MIPS_CONF1_DA_SHF 7
+#define MIPS_CONF1_DA_SZ 3
#define MIPS_CONF1_DA (_ULCAST_(7) << 7)
+#define MIPS_CONF1_DL_SHF 10
+#define MIPS_CONF1_DL_SZ 3
#define MIPS_CONF1_DL (_ULCAST_(7) << 10)
+#define MIPS_CONF1_DS_SHF 13
+#define MIPS_CONF1_DS_SZ 3
#define MIPS_CONF1_DS (_ULCAST_(7) << 13)
+#define MIPS_CONF1_IA_SHF 16
+#define MIPS_CONF1_IA_SZ 3
#define MIPS_CONF1_IA (_ULCAST_(7) << 16)
+#define MIPS_CONF1_IL_SHF 19
+#define MIPS_CONF1_IL_SZ 3
#define MIPS_CONF1_IL (_ULCAST_(7) << 19)
+#define MIPS_CONF1_IS_SHF 22
+#define MIPS_CONF1_IS_SZ 3
#define MIPS_CONF1_IS (_ULCAST_(7) << 22)
-#define MIPS_CONF1_TLBS (_ULCAST_(63)<< 25)
+#define MIPS_CONF1_TLBS_SHIFT (25)
+#define MIPS_CONF1_TLBS_SIZE (6)
+#define MIPS_CONF1_TLBS (_ULCAST_(63) << MIPS_CONF1_TLBS_SHIFT)
#define MIPS_CONF2_SA (_ULCAST_(15)<< 0)
#define MIPS_CONF2_SL (_ULCAST_(15)<< 4)
@@ -587,28 +602,78 @@
#define MIPS_CONF3_TL (_ULCAST_(1) << 0)
#define MIPS_CONF3_SM (_ULCAST_(1) << 1)
#define MIPS_CONF3_MT (_ULCAST_(1) << 2)
+#define MIPS_CONF3_CDMM (_ULCAST_(1) << 3)
#define MIPS_CONF3_SP (_ULCAST_(1) << 4)
#define MIPS_CONF3_VINT (_ULCAST_(1) << 5)
#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6)
#define MIPS_CONF3_LPA (_ULCAST_(1) << 7)
+#define MIPS_CONF3_ITL (_ULCAST_(1) << 8)
+#define MIPS_CONF3_CTXTC (_ULCAST_(1) << 9)
#define MIPS_CONF3_DSP (_ULCAST_(1) << 10)
#define MIPS_CONF3_DSP2P (_ULCAST_(1) << 11)
#define MIPS_CONF3_RXI (_ULCAST_(1) << 12)
#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13)
#define MIPS_CONF3_ISA (_ULCAST_(3) << 14)
#define MIPS_CONF3_ISA_OE (_ULCAST_(1) << 16)
+#define MIPS_CONF3_MCU (_ULCAST_(1) << 17)
+#define MIPS_CONF3_MMAR (_ULCAST_(7) << 18)
+#define MIPS_CONF3_IPLW (_ULCAST_(3) << 21)
#define MIPS_CONF3_VZ (_ULCAST_(1) << 23)
-
+#define MIPS_CONF3_PW (_ULCAST_(1) << 24)
+#define MIPS_CONF3_SC (_ULCAST_(1) << 25)
+#define MIPS_CONF3_BI (_ULCAST_(1) << 26)
+#define MIPS_CONF3_BP (_ULCAST_(1) << 27)
+#define MIPS_CONF3_MSA (_ULCAST_(1) << 28)
+#define MIPS_CONF3_CMGCR (_ULCAST_(1) << 29)
+#define MIPS_CONF3_BPG (_ULCAST_(1) << 30)
+
+#define MIPS_CONF4_MMUSIZEEXT_SHIFT (0)
#define MIPS_CONF4_MMUSIZEEXT (_ULCAST_(255) << 0)
+#define MIPS_CONF4_FTLBSETS_SHIFT (0)
+#define MIPS_CONF4_FTLBSETS_SHIFT (0)
+#define MIPS_CONF4_FTLBSETS (_ULCAST_(15) << MIPS_CONF4_FTLBSETS_SHIFT)
+#define MIPS_CONF4_FTLBWAYS_SHIFT (4)
+#define MIPS_CONF4_FTLBWAYS (_ULCAST_(15) << MIPS_CONF4_FTLBWAYS_SHIFT)
+#define MIPS_CONF4_FTLBPAGESIZE_SHIFT (8)
+/* bits 10:8 in FTLB-only configurations */
+#define MIPS_CONF4_FTLBPAGESIZE (_ULCAST_(7) << MIPS_CONF4_FTLBPAGESIZE_SHIFT)
+/* bits 12:8 in VTLB-FTLB only configurations */
+#define MIPS_CONF4_VFTLBPAGESIZE (_ULCAST_(31) << MIPS_CONF4_FTLBPAGESIZE_SHIFT)
#define MIPS_CONF4_MMUEXTDEF (_ULCAST_(3) << 14)
#define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14)
+#define MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT (_ULCAST_(2) << 14)
+#define MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT (_ULCAST_(3) << 14)
+#define MIPS_CONF4_KSCREXIST (_ULCAST_(255) << 16)
+#define MIPS_CONF4_VTLBSIZEEXT_SHIFT (24)
+#define MIPS_CONF4_VTLBSIZEEXT (_ULCAST_(15) << MIPS_CONF4_VTLBSIZEEXT_SHIFT)
+#define MIPS_CONF4_AE (_ULCAST_(1) << 28)
+#define MIPS_CONF4_IE (_ULCAST_(3) << 29)
+#define MIPS_CONF4_TLBINV (_ULCAST_(2) << 29)
+
+#define MIPS_CONF5_NF (_ULCAST_(1) << 0)
+#define MIPS_CONF5_UFR (_ULCAST_(1) << 2)
+#define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27)
+#define MIPS_CONF5_EVA (_ULCAST_(1) << 28)
+#define MIPS_CONF5_CV (_ULCAST_(1) << 29)
+#define MIPS_CONF5_K (_ULCAST_(1) << 30)
#define MIPS_CONF6_SYND (_ULCAST_(1) << 13)
+/* proAptiv FTLB on/off bit */
+#define MIPS_CONF6_FTLBEN (_ULCAST_(1) << 15)
#define MIPS_CONF7_WII (_ULCAST_(1) << 31)
#define MIPS_CONF7_RPS (_ULCAST_(1) << 2)
+#define MIPS_CONF7_IAR (_ULCAST_(1) << 10)
+#define MIPS_CONF7_AR (_ULCAST_(1) << 16)
+
+/* 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))
/*
* Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
@@ -621,14 +686,41 @@
#define MIPS_FPIR_L (_ULCAST_(1) << 21)
#define MIPS_FPIR_F64 (_ULCAST_(1) << 22)
+/*
+ * Bits in the MIPS32 Memory Segmentation registers.
+ */
+#define MIPS_SEGCFG_PA_SHIFT 9
+#define MIPS_SEGCFG_PA (_ULCAST_(127) << MIPS_SEGCFG_PA_SHIFT)
+#define MIPS_SEGCFG_AM_SHIFT 4
+#define MIPS_SEGCFG_AM (_ULCAST_(7) << MIPS_SEGCFG_AM_SHIFT)
+#define MIPS_SEGCFG_EU_SHIFT 3
+#define MIPS_SEGCFG_EU (_ULCAST_(1) << MIPS_SEGCFG_EU_SHIFT)
+#define MIPS_SEGCFG_C_SHIFT 0
+#define MIPS_SEGCFG_C (_ULCAST_(7) << MIPS_SEGCFG_C_SHIFT)
+
+#define MIPS_SEGCFG_UUSK _ULCAST_(7)
+#define MIPS_SEGCFG_USK _ULCAST_(5)
+#define MIPS_SEGCFG_MUSUK _ULCAST_(4)
+#define MIPS_SEGCFG_MUSK _ULCAST_(3)
+#define MIPS_SEGCFG_MSK _ULCAST_(2)
+#define MIPS_SEGCFG_MK _ULCAST_(1)
+#define MIPS_SEGCFG_UK _ULCAST_(0)
+
#ifndef __ASSEMBLY__
/*
- * Macros for handling the ISA mode bit for microMIPS.
+ * Macros for handling the ISA mode bit for MIPS16 and microMIPS.
*/
+#if defined(CONFIG_SYS_SUPPORTS_MIPS16) || \
+ defined(CONFIG_SYS_SUPPORTS_MICROMIPS)
#define get_isa16_mode(x) ((x) & 0x1)
#define msk_isa16_mode(x) ((x) & ~0x1)
#define set_isa16_mode(x) do { (x) |= 0x1; } while(0)
+#else
+#define get_isa16_mode(x) 0
+#define msk_isa16_mode(x) (x)
+#define set_isa16_mode(x) do { } while(0)
+#endif
/*
* microMIPS instructions can be 16-bit or 32-bit in length. This
@@ -642,6 +734,19 @@ static inline int mm_insn_16bit(u16 insn)
}
/*
+ * TLB Invalidate Flush
+ */
+static inline void tlbinvf(void)
+{
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set noreorder\n\t"
+ ".word 0x42000004\n\t" /* tlbinvf */
+ ".set pop");
+}
+
+
+/*
* Functions to access the R10000 performance counters. These are basically
* mfc0 and mtc0 instructions from and to coprocessor register with a 5-bit
* performance counter number encoded into bits 1 ... 5 of the instruction.
@@ -909,19 +1014,8 @@ do { \
#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val)
#define read_c0_status() __read_32bit_c0_register($12, 0)
-#ifdef CONFIG_MIPS_MT_SMTC
-#define write_c0_status(val) \
-do { \
- __write_32bit_c0_register($12, 0, val); \
- __ehb(); \
-} while (0)
-#else
-/*
- * Legacy non-SMTC code, which may be hazardous
- * but which might not support EHB
- */
+
#define write_c0_status(val) __write_32bit_c0_register($12, 0, val)
-#endif /* CONFIG_MIPS_MT_SMTC */
#define read_c0_cause() __read_32bit_c0_register($13, 0)
#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val)
@@ -931,6 +1025,8 @@ do { \
#define read_c0_prid() __read_32bit_c0_register($15, 0)
+#define read_c0_cmgcrbase() __read_ulong_c0_register($15, 3)
+
#define read_c0_config() __read_32bit_c0_register($16, 0)
#define read_c0_config1() __read_32bit_c0_register($16, 1)
#define read_c0_config2() __read_32bit_c0_register($16, 2)
@@ -1095,6 +1191,15 @@ do { \
#define read_c0_ebase() __read_32bit_c0_register($15, 1)
#define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val)
+/* MIPSR3 */
+#define read_c0_segctl0() __read_32bit_c0_register($5, 2)
+#define write_c0_segctl0(val) __write_32bit_c0_register($5, 2, val)
+
+#define read_c0_segctl1() __read_32bit_c0_register($5, 3)
+#define write_c0_segctl1(val) __write_32bit_c0_register($5, 3, val)
+
+#define read_c0_segctl2() __read_32bit_c0_register($5, 4)
+#define write_c0_segctl2(val) __write_32bit_c0_register($5, 4, val)
/* Cavium OCTEON (cnMIPS) */
#define read_c0_cvmcount() __read_ulong_c0_register($9, 6)
@@ -1634,11 +1739,6 @@ static inline void tlb_write_random(void)
/*
* Manipulate bits in a c0 register.
*/
-#ifndef CONFIG_MIPS_MT_SMTC
-/*
- * SMTC Linux requires shutting-down microthread scheduling
- * during CP0 register read-modify-write sequences.
- */
#define __BUILD_SET_C0(name) \
static inline unsigned int \
set_c0_##name(unsigned int set) \
@@ -1677,124 +1777,10 @@ change_c0_##name(unsigned int change, unsigned int val) \
return res; \
}
-#else /* SMTC versions that manage MT scheduling */
-
-#include <linux/irqflags.h>
-
-/*
- * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
- * header file recursion.
- */
-static inline unsigned int __dmt(void)
-{
- int res;
-
- __asm__ __volatile__(
- " .set push \n"
- " .set mips32r2 \n"
- " .set noat \n"
- " .word 0x41610BC1 # dmt $1 \n"
- " ehb \n"
- " move %0, $1 \n"
- " .set pop \n"
- : "=r" (res));
-
- instruction_hazard();
-
- return res;
-}
-
-#define __VPECONTROL_TE_SHIFT 15
-#define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT)
-
-#define __EMT_ENABLE __VPECONTROL_TE
-
-static inline void __emt(unsigned int previous)
-{
- if ((previous & __EMT_ENABLE))
- __asm__ __volatile__(
- " .set mips32r2 \n"
- " .word 0x41600be1 # emt \n"
- " ehb \n"
- " .set mips0 \n");
-}
-
-static inline void __ehb(void)
-{
- __asm__ __volatile__(
- " .set mips32r2 \n"
- " ehb \n" " .set mips0 \n");
-}
-
-/*
- * Note that local_irq_save/restore affect TC-specific IXMT state,
- * not Status.IE as in non-SMTC kernel.
- */
-
-#define __BUILD_SET_C0(name) \
-static inline unsigned int \
-set_c0_##name(unsigned int set) \
-{ \
- unsigned int res; \
- unsigned int new; \
- unsigned int omt; \
- unsigned long flags; \
- \
- local_irq_save(flags); \
- omt = __dmt(); \
- res = read_c0_##name(); \
- new = res | set; \
- write_c0_##name(new); \
- __emt(omt); \
- local_irq_restore(flags); \
- \
- return res; \
-} \
- \
-static inline unsigned int \
-clear_c0_##name(unsigned int clear) \
-{ \
- unsigned int res; \
- unsigned int new; \
- unsigned int omt; \
- unsigned long flags; \
- \
- local_irq_save(flags); \
- omt = __dmt(); \
- res = read_c0_##name(); \
- new = res & ~clear; \
- write_c0_##name(new); \
- __emt(omt); \
- local_irq_restore(flags); \
- \
- return res; \
-} \
- \
-static inline unsigned int \
-change_c0_##name(unsigned int change, unsigned int newbits) \
-{ \
- unsigned int res; \
- unsigned int new; \
- unsigned int omt; \
- unsigned long flags; \
- \
- local_irq_save(flags); \
- \
- omt = __dmt(); \
- res = read_c0_##name(); \
- new = res & ~change; \
- new |= (newbits & change); \
- write_c0_##name(new); \
- __emt(omt); \
- local_irq_restore(flags); \
- \
- return res; \
-}
-#endif
-
__BUILD_SET_C0(status)
__BUILD_SET_C0(cause)
__BUILD_SET_C0(config)
+__BUILD_SET_C0(config5)
__BUILD_SET_C0(intcontrol)
__BUILD_SET_C0(intctl)
__BUILD_SET_C0(srsmap)
@@ -1806,6 +1792,15 @@ __BUILD_SET_C0(brcm_cmt_ctrl)
__BUILD_SET_C0(brcm_config)
__BUILD_SET_C0(brcm_mode)
+/*
+ * Return low 10 bits of ebase.
+ * Note that under KVM (MIPSVZ) this returns vcpu id.
+ */
+static inline unsigned int get_ebase_cpunum(void)
+{
+ return read_c0_ebase() & 0x3ff;
+}
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_MIPSREGS_H */
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 3b29079b542..2e373da5f8e 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -18,27 +18,27 @@
#include <asm/cacheflush.h>
#include <asm/hazards.h>
#include <asm/tlbflush.h>
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/mipsmtregs.h>
-#include <asm/smtc.h>
-#endif /* SMTC */
#include <asm-generic/mm_hooks.h>
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
do { \
extern void tlbmiss_handler_setup_pgd(unsigned long); \
tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \
} while (0)
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+
+#define TLBMISS_HANDLER_RESTORE() \
+ write_c0_xcontext((unsigned long) smp_processor_id() << \
+ SMP_CPUID_REGSHIFT)
+
#define TLBMISS_HANDLER_SETUP() \
do { \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \
- write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
+ TLBMISS_HANDLER_RESTORE(); \
} while (0)
-#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
+#else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
/*
* For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -47,21 +47,14 @@ do { \
*/
extern unsigned long pgd_current[];
-#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
- pgd_current[smp_processor_id()] = (unsigned long)(pgd)
+#define TLBMISS_HANDLER_RESTORE() \
+ write_c0_context((unsigned long) smp_processor_id() << \
+ SMP_CPUID_REGSHIFT)
-#ifdef CONFIG_32BIT
#define TLBMISS_HANDLER_SETUP() \
- write_c0_context((unsigned long) smp_processor_id() << 25); \
+ TLBMISS_HANDLER_RESTORE(); \
back_to_back_c0_hazard(); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
-#ifdef CONFIG_64BIT
-#define TLBMISS_HANDLER_SETUP() \
- write_c0_context((unsigned long) smp_processor_id() << 26); \
- back_to_back_c0_hazard(); \
- TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
@@ -73,13 +66,6 @@ extern unsigned long pgd_current[];
#define ASID_INC 0x10
#define ASID_MASK 0xff0
-#elif defined(CONFIG_MIPS_MT_SMTC)
-
-#define ASID_INC 0x1
-extern unsigned long smtc_asid_mask;
-#define ASID_MASK (smtc_asid_mask)
-#define HW_ASID_MASK 0xff
-/* End SMTC/34K debug hack */
#else /* FIXME: not correct for R6000 */
#define ASID_INC 0x1
@@ -102,7 +88,6 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
-#ifndef CONFIG_MIPS_MT_SMTC
/* Normal, classic MIPS get_new_mmu_context */
static inline void
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
@@ -125,12 +110,6 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
}
-#else /* CONFIG_MIPS_MT_SMTC */
-
-#define get_new_mmu_context(mm, cpu) smtc_get_new_mmu_context((mm), (cpu))
-
-#endif /* CONFIG_MIPS_MT_SMTC */
-
/*
* Initialize the context related info for a new mm_struct
* instance.
@@ -151,46 +130,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
{
unsigned int cpu = smp_processor_id();
unsigned long flags;
-#ifdef CONFIG_MIPS_MT_SMTC
- unsigned long oldasid;
- unsigned long mtflags;
- int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
- local_irq_save(flags);
- mtflags = dvpe();
-#else /* Not SMTC */
local_irq_save(flags);
-#endif /* CONFIG_MIPS_MT_SMTC */
/* Check if our ASID is of an older version and thus invalid */
if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
get_new_mmu_context(next, cpu);
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * If the EntryHi ASID being replaced happens to be
- * the value flagged at ASID recycling time as having
- * an extended life, clear the bit showing it being
- * in use by this "CPU", and if that's the last bit,
- * free up the ASID value for use and flush any old
- * instances of it from the TLB.
- */
- oldasid = (read_c0_entryhi() & ASID_MASK);
- if(smtc_live_asid[mytlb][oldasid]) {
- smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
- if(smtc_live_asid[mytlb][oldasid] == 0)
- smtc_flush_tlb_asid(oldasid);
- }
- /*
- * Tread softly on EntryHi, and so long as we support
- * having ASID_MASK smaller than the hardware maximum,
- * make sure no "soft" bits become "hard"...
- */
- write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
- cpu_asid(cpu, next));
- ehb(); /* Make sure it propagates to TCStatus */
- evpe(mtflags);
-#else
write_c0_entryhi(cpu_asid(cpu, next));
-#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/*
@@ -223,34 +168,12 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
unsigned long flags;
unsigned int cpu = smp_processor_id();
-#ifdef CONFIG_MIPS_MT_SMTC
- unsigned long oldasid;
- unsigned long mtflags;
- int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
-#endif /* CONFIG_MIPS_MT_SMTC */
-
local_irq_save(flags);
/* Unconditionally get a new ASID. */
get_new_mmu_context(next, cpu);
-#ifdef CONFIG_MIPS_MT_SMTC
- /* See comments for similar code above */
- mtflags = dvpe();
- oldasid = read_c0_entryhi() & ASID_MASK;
- if(smtc_live_asid[mytlb][oldasid]) {
- smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
- if(smtc_live_asid[mytlb][oldasid] == 0)
- smtc_flush_tlb_asid(oldasid);
- }
- /* See comments for similar code above */
- write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
- cpu_asid(cpu, next));
- ehb(); /* Make sure it propagates to TCStatus */
- evpe(mtflags);
-#else
write_c0_entryhi(cpu_asid(cpu, next));
-#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP_PGD(next->pgd);
/* mark mmu ownership change */
@@ -268,48 +191,15 @@ static inline void
drop_mmu_context(struct mm_struct *mm, unsigned cpu)
{
unsigned long flags;
-#ifdef CONFIG_MIPS_MT_SMTC
- unsigned long oldasid;
- /* Can't use spinlock because called from TLB flush within DVPE */
- unsigned int prevvpe;
- int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
-#endif /* CONFIG_MIPS_MT_SMTC */
local_irq_save(flags);
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) {
get_new_mmu_context(mm, cpu);
-#ifdef CONFIG_MIPS_MT_SMTC
- /* See comments for similar code above */
- prevvpe = dvpe();
- oldasid = (read_c0_entryhi() & ASID_MASK);
- if (smtc_live_asid[mytlb][oldasid]) {
- smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
- if(smtc_live_asid[mytlb][oldasid] == 0)
- smtc_flush_tlb_asid(oldasid);
- }
- /* See comments for similar code above */
- write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
- | cpu_asid(cpu, mm));
- ehb(); /* Make sure it propagates to TCStatus */
- evpe(prevvpe);
-#else /* not CONFIG_MIPS_MT_SMTC */
write_c0_entryhi(cpu_asid(cpu, mm));
-#endif /* CONFIG_MIPS_MT_SMTC */
} else {
/* will get a new context next time */
-#ifndef CONFIG_MIPS_MT_SMTC
cpu_context(cpu, mm) = 0;
-#else /* SMTC */
- int i;
-
- /* SMTC shares the TLB (and ASIDs) across VPEs */
- for_each_online_cpu(i) {
- if((smtc_status & SMTC_TLB_SHARED)
- || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
- cpu_context(i, mm) = 0;
- }
-#endif /* CONFIG_MIPS_MT_SMTC */
}
local_irq_restore(flags);
}
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 44b705d0826..800fe578dc9 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -126,6 +126,8 @@ search_module_dbetables(unsigned long addr)
#define MODULE_PROC_FAMILY "LOONGSON1 "
#elif defined CONFIG_CPU_LOONGSON2
#define MODULE_PROC_FAMILY "LOONGSON2 "
+#elif defined CONFIG_CPU_LOONGSON3
+#define MODULE_PROC_FAMILY "LOONGSON3 "
#elif defined CONFIG_CPU_CAVIUM_OCTEON
#define MODULE_PROC_FAMILY "OCTEON "
#elif defined CONFIG_CPU_XLR
@@ -142,13 +144,7 @@ search_module_dbetables(unsigned long addr)
#define MODULE_KERNEL_TYPE "64BIT "
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
-#define MODULE_KERNEL_SMTC "MT_SMTC "
-#else
-#define MODULE_KERNEL_SMTC ""
-#endif
-
#define MODULE_ARCH_VERMAGIC \
- MODULE_PROC_FAMILY MODULE_KERNEL_TYPE MODULE_KERNEL_SMTC
+ MODULE_PROC_FAMILY MODULE_KERNEL_TYPE
#endif /* _ASM_MODULE_H */
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
new file mode 100644
index 00000000000..538f6d482db
--- /dev/null
+++ b/arch/mips/include/asm/msa.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013 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 _ASM_MSA_H
+#define _ASM_MSA_H
+
+#include <asm/mipsregs.h>
+
+extern void _save_msa(struct task_struct *);
+extern void _restore_msa(struct task_struct *);
+
+static inline void enable_msa(void)
+{
+ if (cpu_has_msa) {
+ set_c0_config5(MIPS_CONF5_MSAEN);
+ enable_fpu_hazard();
+ }
+}
+
+static inline void disable_msa(void)
+{
+ if (cpu_has_msa) {
+ clear_c0_config5(MIPS_CONF5_MSAEN);
+ disable_fpu_hazard();
+ }
+}
+
+static inline int is_msa_enabled(void)
+{
+ if (!cpu_has_msa)
+ return 0;
+
+ return read_c0_config5() & MIPS_CONF5_MSAEN;
+}
+
+static inline int thread_msa_context_live(void)
+{
+ /*
+ * Check cpu_has_msa only if it's a constant. This will allow the
+ * compiler to optimise out code for CPUs without MSA without adding
+ * an extra redundant check for CPUs with MSA.
+ */
+ if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
+ return 0;
+
+ return test_thread_flag(TIF_MSA_CTX_LIVE);
+}
+
+static inline void save_msa(struct task_struct *t)
+{
+ if (cpu_has_msa)
+ _save_msa(t);
+}
+
+static inline void restore_msa(struct task_struct *t)
+{
+ if (cpu_has_msa)
+ _restore_msa(t);
+}
+
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+
+#define __BUILD_MSA_CTL_REG(name, cs) \
+static inline unsigned int read_msa_##name(void) \
+{ \
+ unsigned int reg; \
+ __asm__ __volatile__( \
+ " .set push\n" \
+ " .set msa\n" \
+ " cfcmsa %0, $" #cs "\n" \
+ " .set pop\n" \
+ : "=r"(reg)); \
+ return reg; \
+} \
+ \
+static inline void write_msa_##name(unsigned int val) \
+{ \
+ __asm__ __volatile__( \
+ " .set push\n" \
+ " .set msa\n" \
+ " ctcmsa $" #cs ", %0\n" \
+ " .set pop\n" \
+ : : "r"(val)); \
+}
+
+#else /* !TOOLCHAIN_SUPPORTS_MSA */
+
+/*
+ * Define functions using .word for the c[ft]cmsa instructions in order to
+ * allow compilation with toolchains that do not support MSA. Once all
+ * toolchains in use support MSA these can be removed.
+ */
+#ifdef CONFIG_CPU_MICROMIPS
+#define CFC_MSA_INSN 0x587e0056
+#define CTC_MSA_INSN 0x583e0816
+#else
+#define CFC_MSA_INSN 0x787e0059
+#define CTC_MSA_INSN 0x783e0819
+#endif
+
+#define __BUILD_MSA_CTL_REG(name, cs) \
+static inline unsigned int read_msa_##name(void) \
+{ \
+ unsigned int reg; \
+ __asm__ __volatile__( \
+ " .set push\n" \
+ " .set noat\n" \
+ " .insn\n" \
+ " .word #CFC_MSA_INSN | (" #cs " << 11)\n" \
+ " move %0, $1\n" \
+ " .set pop\n" \
+ : "=r"(reg)); \
+ return reg; \
+} \
+ \
+static inline void write_msa_##name(unsigned int val) \
+{ \
+ __asm__ __volatile__( \
+ " .set push\n" \
+ " .set noat\n" \
+ " move $1, %0\n" \
+ " .insn\n" \
+ " .word #CTC_MSA_INSN | (" #cs " << 6)\n" \
+ " .set pop\n" \
+ : : "r"(val)); \
+}
+
+#endif /* !TOOLCHAIN_SUPPORTS_MSA */
+
+#define MSA_IR 0
+#define MSA_CSR 1
+#define MSA_ACCESS 2
+#define MSA_SAVE 3
+#define MSA_MODIFY 4
+#define MSA_REQUEST 5
+#define MSA_MAP 6
+#define MSA_UNMAP 7
+
+__BUILD_MSA_CTL_REG(ir, 0)
+__BUILD_MSA_CTL_REG(csr, 1)
+__BUILD_MSA_CTL_REG(access, 2)
+__BUILD_MSA_CTL_REG(save, 3)
+__BUILD_MSA_CTL_REG(modify, 4)
+__BUILD_MSA_CTL_REG(request, 5)
+__BUILD_MSA_CTL_REG(map, 6)
+__BUILD_MSA_CTL_REG(unmap, 7)
+
+/* MSA Implementation Register (MSAIR) */
+#define MSA_IR_REVB 0
+#define MSA_IR_REVF (_ULCAST_(0xff) << MSA_IR_REVB)
+#define MSA_IR_PROCB 8
+#define MSA_IR_PROCF (_ULCAST_(0xff) << MSA_IR_PROCB)
+#define MSA_IR_WRPB 16
+#define MSA_IR_WRPF (_ULCAST_(0x1) << MSA_IR_WRPB)
+
+/* MSA Control & Status Register (MSACSR) */
+#define MSA_CSR_RMB 0
+#define MSA_CSR_RMF (_ULCAST_(0x3) << MSA_CSR_RMB)
+#define MSA_CSR_RM_NEAREST 0
+#define MSA_CSR_RM_TO_ZERO 1
+#define MSA_CSR_RM_TO_POS 2
+#define MSA_CSR_RM_TO_NEG 3
+#define MSA_CSR_FLAGSB 2
+#define MSA_CSR_FLAGSF (_ULCAST_(0x1f) << MSA_CSR_FLAGSB)
+#define MSA_CSR_FLAGS_IB 2
+#define MSA_CSR_FLAGS_IF (_ULCAST_(0x1) << MSA_CSR_FLAGS_IB)
+#define MSA_CSR_FLAGS_UB 3
+#define MSA_CSR_FLAGS_UF (_ULCAST_(0x1) << MSA_CSR_FLAGS_UB)
+#define MSA_CSR_FLAGS_OB 4
+#define MSA_CSR_FLAGS_OF (_ULCAST_(0x1) << MSA_CSR_FLAGS_OB)
+#define MSA_CSR_FLAGS_ZB 5
+#define MSA_CSR_FLAGS_ZF (_ULCAST_(0x1) << MSA_CSR_FLAGS_ZB)
+#define MSA_CSR_FLAGS_VB 6
+#define MSA_CSR_FLAGS_VF (_ULCAST_(0x1) << MSA_CSR_FLAGS_VB)
+#define MSA_CSR_ENABLESB 7
+#define MSA_CSR_ENABLESF (_ULCAST_(0x1f) << MSA_CSR_ENABLESB)
+#define MSA_CSR_ENABLES_IB 7
+#define MSA_CSR_ENABLES_IF (_ULCAST_(0x1) << MSA_CSR_ENABLES_IB)
+#define MSA_CSR_ENABLES_UB 8
+#define MSA_CSR_ENABLES_UF (_ULCAST_(0x1) << MSA_CSR_ENABLES_UB)
+#define MSA_CSR_ENABLES_OB 9
+#define MSA_CSR_ENABLES_OF (_ULCAST_(0x1) << MSA_CSR_ENABLES_OB)
+#define MSA_CSR_ENABLES_ZB 10
+#define MSA_CSR_ENABLES_ZF (_ULCAST_(0x1) << MSA_CSR_ENABLES_ZB)
+#define MSA_CSR_ENABLES_VB 11
+#define MSA_CSR_ENABLES_VF (_ULCAST_(0x1) << MSA_CSR_ENABLES_VB)
+#define MSA_CSR_CAUSEB 12
+#define MSA_CSR_CAUSEF (_ULCAST_(0x3f) << MSA_CSR_CAUSEB)
+#define MSA_CSR_CAUSE_IB 12
+#define MSA_CSR_CAUSE_IF (_ULCAST_(0x1) << MSA_CSR_CAUSE_IB)
+#define MSA_CSR_CAUSE_UB 13
+#define MSA_CSR_CAUSE_UF (_ULCAST_(0x1) << MSA_CSR_CAUSE_UB)
+#define MSA_CSR_CAUSE_OB 14
+#define MSA_CSR_CAUSE_OF (_ULCAST_(0x1) << MSA_CSR_CAUSE_OB)
+#define MSA_CSR_CAUSE_ZB 15
+#define MSA_CSR_CAUSE_ZF (_ULCAST_(0x1) << MSA_CSR_CAUSE_ZB)
+#define MSA_CSR_CAUSE_VB 16
+#define MSA_CSR_CAUSE_VF (_ULCAST_(0x1) << MSA_CSR_CAUSE_VB)
+#define MSA_CSR_CAUSE_EB 17
+#define MSA_CSR_CAUSE_EF (_ULCAST_(0x1) << MSA_CSR_CAUSE_EB)
+#define MSA_CSR_NXB 18
+#define MSA_CSR_NXF (_ULCAST_(0x1) << MSA_CSR_NXB)
+#define MSA_CSR_FSB 24
+#define MSA_CSR_FSF (_ULCAST_(0x1) << MSA_CSR_FSB)
+
+#endif /* _ASM_MSA_H */
diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h
index bb68c3398c8..c281f03eb31 100644
--- a/arch/mips/include/asm/netlogic/common.h
+++ b/arch/mips/include/asm/netlogic/common.h
@@ -84,7 +84,6 @@ nlm_set_nmi_handler(void *handler)
*/
void nlm_init_boot_cpu(void);
unsigned int nlm_get_cpu_frequency(void);
-void nlm_node_init(int node);
extern struct plat_smp_ops nlm_smp_ops;
extern char nlm_reset_entry[], nlm_reset_entry_end[];
@@ -94,26 +93,16 @@ extern struct dma_map_ops nlm_swiotlb_dma_ops;
extern unsigned int nlm_threads_per_core;
extern cpumask_t nlm_cpumask;
-struct nlm_soc_info {
- unsigned long coremask; /* cores enabled on the soc */
- unsigned long ebase;
- uint64_t irqmask;
- uint64_t sysbase; /* only for XLP */
- uint64_t picbase;
- spinlock_t piclock;
-};
-
-#define nlm_get_node(i) (&nlm_nodes[i])
-#ifdef CONFIG_CPU_XLR
-#define nlm_current_node() (&nlm_nodes[0])
-#else
-#define nlm_current_node() (&nlm_nodes[nlm_nodeid()])
-#endif
-
struct irq_data;
uint64_t nlm_pci_irqmask(int node);
+void nlm_setup_pic_irq(int node, int picirq, int irq, int irt);
void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *));
+#ifdef CONFIG_PCI_MSI
+void nlm_dispatch_msi(int node, int lirq);
+void nlm_dispatch_msix(int node, int msixirq);
+#endif
+
/*
* The NR_IRQs is divided between nodes, each of them has a separate irq space
*/
@@ -122,7 +111,6 @@ static inline int nlm_irq_to_xirq(int node, int irq)
return node * NR_IRQS / NLM_NR_NODES + irq;
}
-extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
extern int nlm_cpu_ready[];
#endif
#endif /* _NETLOGIC_COMMON_H_ */
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index f299d31d7c1..06f1f75bfa9 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -146,7 +146,13 @@ static inline int hard_smp_processor_id(void)
static inline int nlm_nodeid(void)
{
- return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
+ uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
+
+ if ((prid == PRID_IMP_NETLOGIC_XLP9XX) ||
+ (prid == PRID_IMP_NETLOGIC_XLP5XX))
+ return (__read_32bit_c0_register($15, 1) >> 7) & 0x7;
+ else
+ return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
}
static inline unsigned int nlm_core_id(void)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/bridge.h b/arch/mips/include/asm/netlogic/xlp-hal/bridge.h
index 4e8eacb9588..3067f983495 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/bridge.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/bridge.h
@@ -69,44 +69,9 @@
#define BRIDGE_FLASH_LIMIT3 0x13
#define BRIDGE_DRAM_BAR(i) (0x14 + (i))
-#define BRIDGE_DRAM_BAR0 0x14
-#define BRIDGE_DRAM_BAR1 0x15
-#define BRIDGE_DRAM_BAR2 0x16
-#define BRIDGE_DRAM_BAR3 0x17
-#define BRIDGE_DRAM_BAR4 0x18
-#define BRIDGE_DRAM_BAR5 0x19
-#define BRIDGE_DRAM_BAR6 0x1a
-#define BRIDGE_DRAM_BAR7 0x1b
-
#define BRIDGE_DRAM_LIMIT(i) (0x1c + (i))
-#define BRIDGE_DRAM_LIMIT0 0x1c
-#define BRIDGE_DRAM_LIMIT1 0x1d
-#define BRIDGE_DRAM_LIMIT2 0x1e
-#define BRIDGE_DRAM_LIMIT3 0x1f
-#define BRIDGE_DRAM_LIMIT4 0x20
-#define BRIDGE_DRAM_LIMIT5 0x21
-#define BRIDGE_DRAM_LIMIT6 0x22
-#define BRIDGE_DRAM_LIMIT7 0x23
-
#define BRIDGE_DRAM_NODE_TRANSLN(i) (0x24 + (i))
-#define BRIDGE_DRAM_NODE_TRANSLN0 0x24
-#define BRIDGE_DRAM_NODE_TRANSLN1 0x25
-#define BRIDGE_DRAM_NODE_TRANSLN2 0x26
-#define BRIDGE_DRAM_NODE_TRANSLN3 0x27
-#define BRIDGE_DRAM_NODE_TRANSLN4 0x28
-#define BRIDGE_DRAM_NODE_TRANSLN5 0x29
-#define BRIDGE_DRAM_NODE_TRANSLN6 0x2a
-#define BRIDGE_DRAM_NODE_TRANSLN7 0x2b
-
#define BRIDGE_DRAM_CHNL_TRANSLN(i) (0x2c + (i))
-#define BRIDGE_DRAM_CHNL_TRANSLN0 0x2c
-#define BRIDGE_DRAM_CHNL_TRANSLN1 0x2d
-#define BRIDGE_DRAM_CHNL_TRANSLN2 0x2e
-#define BRIDGE_DRAM_CHNL_TRANSLN3 0x2f
-#define BRIDGE_DRAM_CHNL_TRANSLN4 0x30
-#define BRIDGE_DRAM_CHNL_TRANSLN5 0x31
-#define BRIDGE_DRAM_CHNL_TRANSLN6 0x32
-#define BRIDGE_DRAM_CHNL_TRANSLN7 0x33
#define BRIDGE_PCIEMEM_BASE0 0x34
#define BRIDGE_PCIEMEM_BASE1 0x35
@@ -178,12 +143,42 @@
#define BRIDGE_GIO_WEIGHT 0x2cb
#define BRIDGE_FLASH_WEIGHT 0x2cc
+/* FIXME verify */
+#define BRIDGE_9XX_FLASH_BAR(i) (0x11 + (i))
+#define BRIDGE_9XX_FLASH_BAR_LIMIT(i) (0x15 + (i))
+
+#define BRIDGE_9XX_DRAM_BAR(i) (0x19 + (i))
+#define BRIDGE_9XX_DRAM_LIMIT(i) (0x29 + (i))
+#define BRIDGE_9XX_DRAM_NODE_TRANSLN(i) (0x39 + (i))
+#define BRIDGE_9XX_DRAM_CHNL_TRANSLN(i) (0x49 + (i))
+
+#define BRIDGE_9XX_ADDRESS_ERROR0 0x9d
+#define BRIDGE_9XX_ADDRESS_ERROR1 0x9e
+#define BRIDGE_9XX_ADDRESS_ERROR2 0x9f
+
+#define BRIDGE_9XX_PCIEMEM_BASE0 0x59
+#define BRIDGE_9XX_PCIEMEM_BASE1 0x5a
+#define BRIDGE_9XX_PCIEMEM_BASE2 0x5b
+#define BRIDGE_9XX_PCIEMEM_BASE3 0x5c
+#define BRIDGE_9XX_PCIEMEM_LIMIT0 0x5d
+#define BRIDGE_9XX_PCIEMEM_LIMIT1 0x5e
+#define BRIDGE_9XX_PCIEMEM_LIMIT2 0x5f
+#define BRIDGE_9XX_PCIEMEM_LIMIT3 0x60
+#define BRIDGE_9XX_PCIEIO_BASE0 0x61
+#define BRIDGE_9XX_PCIEIO_BASE1 0x62
+#define BRIDGE_9XX_PCIEIO_BASE2 0x63
+#define BRIDGE_9XX_PCIEIO_BASE3 0x64
+#define BRIDGE_9XX_PCIEIO_LIMIT0 0x65
+#define BRIDGE_9XX_PCIEIO_LIMIT1 0x66
+#define BRIDGE_9XX_PCIEIO_LIMIT2 0x67
+#define BRIDGE_9XX_PCIEIO_LIMIT3 0x68
+
#ifndef __ASSEMBLY__
#define nlm_read_bridge_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_bridge_reg(b, r, v) nlm_write_reg(b, r, v)
-#define nlm_get_bridge_pcibase(node) \
- nlm_pcicfg_base(XLP_IO_BRIDGE_OFFSET(node))
+#define nlm_get_bridge_pcibase(node) nlm_pcicfg_base(cpu_is_xlp9xx() ? \
+ XLP9XX_IO_BRIDGE_OFFSET(node) : XLP_IO_BRIDGE_OFFSET(node))
#define nlm_get_bridge_regbase(node) \
(nlm_get_bridge_pcibase(node) + XLP_IO_PCI_HDRSZ)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
index 55eee77adac..805bfd21f33 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h
@@ -48,8 +48,10 @@
#define XLP_IO_SIZE (64 << 20) /* ECFG space size */
#define XLP_IO_PCI_HDRSZ 0x100
#define XLP_IO_DEV(node, dev) ((dev) + (node) * 8)
-#define XLP_HDR_OFFSET(node, bus, dev, fn) (((bus) << 20) | \
- ((XLP_IO_DEV(node, dev)) << 15) | ((fn) << 12))
+#define XLP_IO_PCI_OFFSET(b, d, f) (((b) << 20) | ((d) << 15) | ((f) << 12))
+
+#define XLP_HDR_OFFSET(node, bus, dev, fn) \
+ XLP_IO_PCI_OFFSET(bus, XLP_IO_DEV(node, dev), fn)
#define XLP_IO_BRIDGE_OFFSET(node) XLP_HDR_OFFSET(node, 0, 0, 0)
/* coherent inter chip */
@@ -72,6 +74,8 @@
#define XLP_IO_USB_OHCI2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 4)
#define XLP_IO_USB_OHCI3_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 5)
+#define XLP_IO_SATA_OFFSET(node) XLP_HDR_OFFSET(node, 0, 3, 2)
+
/* XLP2xx has an updated USB block */
#define XLP2XX_IO_USB_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 4, i)
#define XLP2XX_IO_USB_XHCI0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 4, 1)
@@ -101,13 +105,43 @@
#define XLP_IO_SYS_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 5)
#define XLP_IO_JTAG_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 6)
+/* Flash */
#define XLP_IO_NOR_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 0)
#define XLP_IO_NAND_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 1)
#define XLP_IO_SPI_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 2)
-/* SD flash */
-#define XLP_IO_SD_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 3)
-#define XLP_IO_MMC_OFFSET(node, slot) \
- ((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
+#define XLP_IO_MMC_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 3)
+
+/* Things have changed drastically in XLP 9XX */
+#define XLP9XX_HDR_OFFSET(n, d, f) \
+ XLP_IO_PCI_OFFSET(xlp9xx_get_socbus(n), d, f)
+
+#define XLP9XX_IO_BRIDGE_OFFSET(node) XLP_IO_PCI_OFFSET(0, 0, node)
+#define XLP9XX_IO_PIC_OFFSET(node) XLP9XX_HDR_OFFSET(node, 2, 0)
+#define XLP9XX_IO_UART_OFFSET(node) XLP9XX_HDR_OFFSET(node, 2, 2)
+#define XLP9XX_IO_SYS_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 0)
+#define XLP9XX_IO_FUSE_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 1)
+#define XLP9XX_IO_CLOCK_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 2)
+#define XLP9XX_IO_POWER_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 3)
+#define XLP9XX_IO_JTAG_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 4)
+
+#define XLP9XX_IO_PCIE_OFFSET(node, i) XLP9XX_HDR_OFFSET(node, 1, i)
+#define XLP9XX_IO_PCIE0_OFFSET(node) XLP9XX_HDR_OFFSET(node, 1, 0)
+#define XLP9XX_IO_PCIE2_OFFSET(node) XLP9XX_HDR_OFFSET(node, 1, 2)
+#define XLP9XX_IO_PCIE3_OFFSET(node) XLP9XX_HDR_OFFSET(node, 1, 3)
+
+/* XLP9xx USB block */
+#define XLP9XX_IO_USB_OFFSET(node, i) XLP9XX_HDR_OFFSET(node, 4, i)
+#define XLP9XX_IO_USB_XHCI0_OFFSET(node) XLP9XX_HDR_OFFSET(node, 4, 1)
+#define XLP9XX_IO_USB_XHCI1_OFFSET(node) XLP9XX_HDR_OFFSET(node, 4, 2)
+
+/* XLP9XX on-chip SATA controller */
+#define XLP9XX_IO_SATA_OFFSET(node) XLP9XX_HDR_OFFSET(node, 3, 2)
+
+/* Flash */
+#define XLP9XX_IO_NOR_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 0)
+#define XLP9XX_IO_NAND_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 1)
+#define XLP9XX_IO_SPI_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 2)
+#define XLP9XX_IO_MMC_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 3)
/* PCI config header register id's */
#define XLP_PCI_CFGREG0 0x00
@@ -154,13 +188,27 @@
#define PCI_DEVICE_ID_NLM_NOR 0x1015
#define PCI_DEVICE_ID_NLM_NAND 0x1016
#define PCI_DEVICE_ID_NLM_MMC 0x1018
-#define PCI_DEVICE_ID_NLM_XHCI 0x101d
+#define PCI_DEVICE_ID_NLM_SATA 0x101A
+#define PCI_DEVICE_ID_NLM_XHCI 0x101D
+
+#define PCI_DEVICE_ID_XLP9XX_MMC 0x9018
+#define PCI_DEVICE_ID_XLP9XX_SATA 0x901A
+#define PCI_DEVICE_ID_XLP9XX_XHCI 0x901D
#ifndef __ASSEMBLY__
#define nlm_read_pci_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_pci_reg(b, r, v) nlm_write_reg(b, r, v)
+static inline int xlp9xx_get_socbus(int node)
+{
+ uint64_t socbridge;
+
+ if (node == 0)
+ return 1;
+ socbridge = nlm_pcicfg_base(XLP9XX_IO_BRIDGE_OFFSET(node));
+ return (nlm_read_pci_reg(socbridge, 0x6) >> 8) & 0xff;
+}
#endif /* !__ASSEMBLY */
#endif /* __NLM_HAL_IOMAP_H__ */
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
index b559cb9f56e..91540f41e1e 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
@@ -52,25 +52,62 @@
#define PCIE_BYTE_SWAP_MEM_LIM 0x248
#define PCIE_BYTE_SWAP_IO_BASE 0x249
#define PCIE_BYTE_SWAP_IO_LIM 0x24A
+
+#define PCIE_BRIDGE_MSIX_ADDR_BASE 0x24F
+#define PCIE_BRIDGE_MSIX_ADDR_LIMIT 0x250
#define PCIE_MSI_STATUS 0x25A
#define PCIE_MSI_EN 0x25B
+#define PCIE_MSIX_STATUS 0x25D
+#define PCIE_INT_STATUS0 0x25F
+#define PCIE_INT_STATUS1 0x260
#define PCIE_INT_EN0 0x261
+#define PCIE_INT_EN1 0x262
+
+/* XLP9XX has basic changes */
+#define PCIE_9XX_BYTE_SWAP_MEM_BASE 0x25c
+#define PCIE_9XX_BYTE_SWAP_MEM_LIM 0x25d
+#define PCIE_9XX_BYTE_SWAP_IO_BASE 0x25e
+#define PCIE_9XX_BYTE_SWAP_IO_LIM 0x25f
-/* PCIE_MSI_EN */
-#define PCIE_MSI_VECTOR_INT_EN 0xFFFFFFFF
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE 0x264
+#define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT 0x265
+#define PCIE_9XX_MSI_STATUS 0x283
+#define PCIE_9XX_MSI_EN 0x284
+/* 128 MSIX vectors available in 9xx */
+#define PCIE_9XX_MSIX_STATUS0 0x286
+#define PCIE_9XX_MSIX_STATUSX(n) (n + 0x286)
+#define PCIE_9XX_MSIX_VEC 0x296
+#define PCIE_9XX_MSIX_VECX(n) (n + 0x296)
+#define PCIE_9XX_INT_STATUS0 0x397
+#define PCIE_9XX_INT_STATUS1 0x398
+#define PCIE_9XX_INT_EN0 0x399
+#define PCIE_9XX_INT_EN1 0x39a
-/* PCIE_INT_EN0 */
-#define PCIE_MSI_INT_EN (1 << 9)
+/* other */
+#define PCIE_NLINKS 4
+/* MSI addresses */
+#define MSI_ADDR_BASE 0xfffee00000ULL
+#define MSI_ADDR_SZ 0x10000
+#define MSI_LINK_ADDR(n, l) (MSI_ADDR_BASE + \
+ (PCIE_NLINKS * (n) + (l)) * MSI_ADDR_SZ)
+#define MSIX_ADDR_BASE 0xfffef00000ULL
+#define MSIX_LINK_ADDR(n, l) (MSIX_ADDR_BASE + \
+ (PCIE_NLINKS * (n) + (l)) * MSI_ADDR_SZ)
#ifndef __ASSEMBLY__
#define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_pcie_reg(b, r, v) nlm_write_reg(b, r, v)
-#define nlm_get_pcie_base(node, inst) \
- nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, inst))
-#define nlm_get_pcie_regbase(node, inst) \
- (nlm_get_pcie_base(node, inst) + XLP_IO_PCI_HDRSZ)
+#define nlm_get_pcie_base(node, inst) nlm_pcicfg_base(cpu_is_xlp9xx() ? \
+ XLP9XX_IO_PCIE_OFFSET(node, inst) : XLP_IO_PCIE_OFFSET(node, inst))
+
+#ifdef CONFIG_PCI_MSI
+void xlp_init_node_msi_irqs(int node, int link);
+#else
+static inline void xlp_init_node_msi_irqs(int node, int link) {}
+#endif
+
+struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev);
-int xlp_pcie_link_irt(int link);
#endif
#endif /* __NLM_HAL_PCIBUS_H__ */
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
index 105389b79f0..41cefe94f0c 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h
@@ -150,12 +150,19 @@
#define PIC_IRT0 0x74
#define PIC_IRT(i) (PIC_IRT0 + ((i) * 2))
-#define TIMER_CYCLES_MAXVAL 0xffffffffffffffffULL
+#define PIC_9XX_PENDING_0 0x6
+#define PIC_9XX_PENDING_1 0x8
+#define PIC_9XX_PENDING_2 0xa
+#define PIC_9XX_PENDING_3 0xc
+
+#define PIC_9XX_IRT0 0x1c0
+#define PIC_9XX_IRT(i) (PIC_9XX_IRT0 + ((i) * 2))
/*
* IRT Map
*/
#define PIC_NUM_IRTS 160
+#define PIC_9XX_NUM_IRTS 256
#define PIC_IRT_WD_0_INDEX 0
#define PIC_IRT_WD_1_INDEX 1
@@ -192,15 +199,14 @@
#define PIC_IRT_PCIE_LINK_3_INDEX 81
#define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX)
+#define PIC_9XX_IRT_PCIE_LINK_0_INDEX 191
+#define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \
+ ((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX)
+
#define PIC_CLOCK_TIMER 7
-#define PIC_IRQ_BASE 8
#if !defined(LOCORE) && !defined(__ASSEMBLY__)
-#define PIC_IRT_FIRST_IRQ (PIC_IRQ_BASE)
-#define PIC_IRT_LAST_IRQ 63
-#define PIC_IRQ_IS_IRT(irq) ((irq) >= PIC_IRT_FIRST_IRQ)
-
/*
* Misc
*/
@@ -210,30 +216,26 @@
#define nlm_read_pic_reg(b, r) nlm_read_reg64(b, r)
#define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v)
-#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node))
+#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(cpu_is_xlp9xx() ? \
+ XLP9XX_IO_PIC_OFFSET(node) : XLP_IO_PIC_OFFSET(node))
#define nlm_get_pic_regbase(node) (nlm_get_pic_pcibase(node) + XLP_IO_PCI_HDRSZ)
/* We use PIC on node 0 as a timer */
#define pic_timer_freq() nlm_get_pic_frequency(0)
/* IRT and h/w interrupt routines */
-static inline int
-nlm_pic_read_irt(uint64_t base, int irt_index)
-{
- return nlm_read_pic_reg(base, PIC_IRT(irt_index));
-}
-
static inline void
-nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu)
+nlm_9xx_pic_write_irt(uint64_t base, int irt_num, int en, int nmi,
+ int sch, int vec, int dt, int db, int cpu)
{
uint64_t val;
- val = nlm_read_pic_reg(base, PIC_IRT(irt));
- /* clear cpuset and mask */
- val &= ~((0x7ull << 16) | 0xffff);
- /* set DB, cpuset and cpumask */
- val |= (1 << 19) | ((cpu >> 4) << 16) | (1 << (cpu & 0xf));
- nlm_write_pic_reg(base, PIC_IRT(irt), val);
+ val = (((uint64_t)en & 0x1) << 22) | ((nmi & 0x1) << 23) |
+ ((0 /*mc*/) << 20) | ((vec & 0x3f) << 24) |
+ ((dt & 0x1) << 21) | (0 /*ptr*/ << 16) |
+ (cpu & 0x3ff);
+
+ nlm_write_pic_reg(base, PIC_9XX_IRT(irt_num), val);
}
static inline void
@@ -254,9 +256,13 @@ static inline void
nlm_pic_write_irt_direct(uint64_t base, int irt_num, int en, int nmi,
int sch, int vec, int cpu)
{
- nlm_pic_write_irt(base, irt_num, en, nmi, sch, vec, 1,
- (cpu >> 4), /* thread group */
- 1 << (cpu & 0xf)); /* thread mask */
+ if (cpu_is_xlp9xx())
+ nlm_9xx_pic_write_irt(base, irt_num, en, nmi, sch, vec,
+ 1, 0, cpu);
+ else
+ nlm_pic_write_irt(base, irt_num, en, nmi, sch, vec, 1,
+ (cpu >> 4), /* thread group */
+ 1 << (cpu & 0xf)); /* thread mask */
}
static inline uint64_t
@@ -298,8 +304,13 @@ nlm_pic_enable_irt(uint64_t base, int irt)
{
uint64_t reg;
- reg = nlm_read_pic_reg(base, PIC_IRT(irt));
- nlm_write_pic_reg(base, PIC_IRT(irt), reg | (1u << 31));
+ if (cpu_is_xlp9xx()) {
+ reg = nlm_read_pic_reg(base, PIC_9XX_IRT(irt));
+ nlm_write_pic_reg(base, PIC_9XX_IRT(irt), reg | (1 << 22));
+ } else {
+ reg = nlm_read_pic_reg(base, PIC_IRT(irt));
+ nlm_write_pic_reg(base, PIC_IRT(irt), reg | (1u << 31));
+ }
}
static inline void
@@ -307,8 +318,15 @@ nlm_pic_disable_irt(uint64_t base, int irt)
{
uint64_t reg;
- reg = nlm_read_pic_reg(base, PIC_IRT(irt));
- nlm_write_pic_reg(base, PIC_IRT(irt), reg & ~((uint64_t)1 << 31));
+ if (cpu_is_xlp9xx()) {
+ reg = nlm_read_pic_reg(base, PIC_9XX_IRT(irt));
+ reg &= ~((uint64_t)1 << 22);
+ nlm_write_pic_reg(base, PIC_9XX_IRT(irt), reg);
+ } else {
+ reg = nlm_read_pic_reg(base, PIC_IRT(irt));
+ reg &= ~((uint64_t)1 << 31);
+ nlm_write_pic_reg(base, PIC_IRT(irt), reg);
+ }
}
static inline void
@@ -316,8 +334,13 @@ nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi)
{
uint64_t ipi;
- ipi = ((uint64_t)nmi << 31) | (irq << 20);
- ipi |= ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); /* cpuset and mask */
+ if (cpu_is_xlp9xx())
+ ipi = (nmi << 23) | (irq << 24) |
+ (0/*mcm*/ << 20) | (0/*ptr*/ << 16) | hwt;
+ else
+ ipi = ((uint64_t)nmi << 31) | (irq << 20) |
+ ((hwt >> 4) << 16) | (1 << (hwt & 0xf));
+
nlm_write_pic_reg(base, PIC_IPI_CTL, ipi);
}
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
index fcf2833c16c..bc7bddf25be 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h
@@ -118,6 +118,10 @@
#define SYS_SCRTCH3 0x4c
/* PLL registers XLP2XX */
+#define SYS_CPU_PLL_CTRL0(core) (0x1c0 + (core * 4))
+#define SYS_CPU_PLL_CTRL1(core) (0x1c1 + (core * 4))
+#define SYS_CPU_PLL_CTRL2(core) (0x1c2 + (core * 4))
+#define SYS_CPU_PLL_CTRL3(core) (0x1c3 + (core * 4))
#define SYS_PLL_CTRL0 0x240
#define SYS_PLL_CTRL1 0x241
#define SYS_PLL_CTRL2 0x242
@@ -147,13 +151,60 @@
#define SYS_SYS_PLL_MEM_REQ 0x2a3
#define SYS_PLL_MEM_STAT 0x2a4
+/* PLL registers XLP9XX */
+#define SYS_9XX_CPU_PLL_CTRL0(core) (0xc0 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL1(core) (0xc1 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL2(core) (0xc2 + (core * 4))
+#define SYS_9XX_CPU_PLL_CTRL3(core) (0xc3 + (core * 4))
+#define SYS_9XX_DMC_PLL_CTRL0 0x140
+#define SYS_9XX_DMC_PLL_CTRL1 0x141
+#define SYS_9XX_DMC_PLL_CTRL2 0x142
+#define SYS_9XX_DMC_PLL_CTRL3 0x143
+#define SYS_9XX_PLL_CTRL0 0x144
+#define SYS_9XX_PLL_CTRL1 0x145
+#define SYS_9XX_PLL_CTRL2 0x146
+#define SYS_9XX_PLL_CTRL3 0x147
+
+#define SYS_9XX_PLL_CTRL0_DEVX(x) (0x148 + (x) * 4)
+#define SYS_9XX_PLL_CTRL1_DEVX(x) (0x149 + (x) * 4)
+#define SYS_9XX_PLL_CTRL2_DEVX(x) (0x14a + (x) * 4)
+#define SYS_9XX_PLL_CTRL3_DEVX(x) (0x14b + (x) * 4)
+
+#define SYS_9XX_CPU_PLL_CHG_CTRL 0x188
+#define SYS_9XX_PLL_CHG_CTRL 0x189
+#define SYS_9XX_CLK_DEV_DIS 0x18a
+#define SYS_9XX_CLK_DEV_SEL 0x18b
+#define SYS_9XX_CLK_DEV_DIV 0x18d
+#define SYS_9XX_CLK_DEV_CHG 0x18f
+
+/* Registers changed on 9XX */
+#define SYS_9XX_POWER_ON_RESET_CFG 0x00
+#define SYS_9XX_CHIP_RESET 0x01
+#define SYS_9XX_CPU_RESET 0x02
+#define SYS_9XX_CPU_NONCOHERENT_MODE 0x03
+
+/* XLP 9XX fuse block registers */
+#define FUSE_9XX_DEVCFG6 0xc6
+
#ifndef __ASSEMBLY__
#define nlm_read_sys_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_sys_reg(b, r, v) nlm_write_reg(b, r, v)
-#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
+#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(cpu_is_xlp9xx() ? \
+ XLP9XX_IO_SYS_OFFSET(node) : XLP_IO_SYS_OFFSET(node))
#define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ)
+/* XLP9XX fuse block */
+#define nlm_get_fuse_pcibase(node) \
+ nlm_pcicfg_base(XLP9XX_IO_FUSE_OFFSET(node))
+#define nlm_get_fuse_regbase(node) \
+ (nlm_get_fuse_pcibase(node) + XLP_IO_PCI_HDRSZ)
+
+#define nlm_get_clock_pcibase(node) \
+ nlm_pcicfg_base(XLP9XX_IO_CLOCK_OFFSET(node))
+#define nlm_get_clock_regbase(node) \
+ (nlm_get_clock_pcibase(node) + XLP_IO_PCI_HDRSZ)
+
unsigned int nlm_get_pic_frequency(int node);
#endif
#endif
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/uart.h b/arch/mips/include/asm/netlogic/xlp-hal/uart.h
index 86d16e1e607..a6c54424dd9 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/uart.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/uart.h
@@ -94,7 +94,8 @@
#define nlm_read_uart_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_uart_reg(b, r, v) nlm_write_reg(b, r, v)
#define nlm_get_uart_pcibase(node, inst) \
- nlm_pcicfg_base(XLP_IO_UART_OFFSET(node, inst))
+ nlm_pcicfg_base(cpu_is_xlp9xx() ? XLP9XX_IO_UART_OFFSET(node) : \
+ XLP_IO_UART_OFFSET(node, inst))
#define nlm_get_uart_regbase(node, inst) \
(nlm_get_uart_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 17daffb280a..a862b93223c 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -37,10 +37,9 @@
#define PIC_UART_0_IRQ 17
#define PIC_UART_1_IRQ 18
-#define PIC_PCIE_LINK_0_IRQ 19
-#define PIC_PCIE_LINK_1_IRQ 20
-#define PIC_PCIE_LINK_2_IRQ 21
-#define PIC_PCIE_LINK_3_IRQ 22
+
+#define PIC_PCIE_LINK_LEGACY_IRQ_BASE 19
+#define PIC_PCIE_LINK_LEGACY_IRQ(i) (19 + (i))
#define PIC_EHCI_0_IRQ 23
#define PIC_EHCI_1_IRQ 24
@@ -51,12 +50,36 @@
#define PIC_2XX_XHCI_0_IRQ 23
#define PIC_2XX_XHCI_1_IRQ 24
#define PIC_2XX_XHCI_2_IRQ 25
+#define PIC_9XX_XHCI_0_IRQ 23
+#define PIC_9XX_XHCI_1_IRQ 24
#define PIC_MMC_IRQ 29
#define PIC_I2C_0_IRQ 30
#define PIC_I2C_1_IRQ 31
#define PIC_I2C_2_IRQ 32
#define PIC_I2C_3_IRQ 33
+#define PIC_SPI_IRQ 34
+#define PIC_NAND_IRQ 37
+#define PIC_SATA_IRQ 38
+#define PIC_GPIO_IRQ 39
+
+#define PIC_PCIE_LINK_MSI_IRQ_BASE 44 /* 44 - 47 MSI IRQ */
+#define PIC_PCIE_LINK_MSI_IRQ(i) (44 + (i))
+
+/* MSI-X with second link-level dispatch */
+#define PIC_PCIE_MSIX_IRQ_BASE 48 /* 48 - 51 MSI-X IRQ */
+#define PIC_PCIE_MSIX_IRQ(i) (48 + (i))
+
+/* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */
+#define NLM_MSIX_VEC_BASE 96 /* 96 - 223 - MSIX mapped */
+#define NLM_MSI_VEC_BASE 224 /* 224 -351 - MSI mapped */
+
+#define NLM_PIC_INDIRECT_VEC_BASE 512
+#define NLM_GPIO_VEC_BASE 768
+
+#define PIC_IRQ_BASE 8
+#define PIC_IRT_FIRST_IRQ PIC_IRQ_BASE
+#define PIC_IRT_LAST_IRQ 63
#ifndef __ASSEMBLY__
@@ -68,15 +91,28 @@ void xlp_mmu_init(void);
void nlm_hal_init(void);
int xlp_get_dram_map(int n, uint64_t *dram_map);
+struct pci_dev;
+int xlp_socdev_to_node(const struct pci_dev *dev);
+
/* Device tree related */
+void xlp_early_init_devtree(void);
void *xlp_dt_init(void *fdtp);
static inline int cpu_is_xlpii(void)
{
- int chip = read_c0_prid() & 0xff00;
+ int chip = read_c0_prid() & PRID_IMP_MASK;
- return chip == PRID_IMP_NETLOGIC_XLP2XX;
+ return chip == PRID_IMP_NETLOGIC_XLP2XX ||
+ chip == PRID_IMP_NETLOGIC_XLP9XX ||
+ chip == PRID_IMP_NETLOGIC_XLP5XX;
}
+static inline int cpu_is_xlp9xx(void)
+{
+ int chip = read_c0_prid() & PRID_IMP_MASK;
+
+ return chip == PRID_IMP_NETLOGIC_XLP9XX ||
+ chip == PRID_IMP_NETLOGIC_XLP5XX;
+}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_NLM_XLP_H */
diff --git a/arch/mips/include/asm/netlogic/xlr/xlr.h b/arch/mips/include/asm/netlogic/xlr/xlr.h
index c1667e0c272..ceb991ca843 100644
--- a/arch/mips/include/asm/netlogic/xlr/xlr.h
+++ b/arch/mips/include/asm/netlogic/xlr/xlr.h
@@ -35,11 +35,6 @@
#ifndef _ASM_NLM_XLR_H
#define _ASM_NLM_XLR_H
-/* Platform UART functions */
-struct uart_port;
-unsigned int nlm_xlr_uart_in(struct uart_port *, int);
-void nlm_xlr_uart_out(struct uart_port *, int, int);
-
/* SMP helpers */
void xlr_wakeup_secondary_cpus(void);
diff --git a/arch/mips/include/asm/nile4.h b/arch/mips/include/asm/nile4.h
index 2e2436d0e94..99e97f8bfbc 100644
--- a/arch/mips/include/asm/nile4.h
+++ b/arch/mips/include/asm/nile4.h
@@ -1,7 +1,7 @@
/*
* asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions
*
- * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@linux-m68k.org>
* Sony Software Development Center Europe (SDCE), Brussels
*
* This file is based on the following documentation:
diff --git a/arch/mips/include/asm/octeon/cvmx-helper-board.h b/arch/mips/include/asm/octeon/cvmx-helper-board.h
index 41785dd0ddd..893320375ae 100644
--- a/arch/mips/include/asm/octeon/cvmx-helper-board.h
+++ b/arch/mips/include/asm/octeon/cvmx-helper-board.h
@@ -36,6 +36,13 @@
#include <asm/octeon/cvmx-helper.h>
+enum cvmx_helper_board_usb_clock_types {
+ USB_CLOCK_TYPE_REF_12,
+ USB_CLOCK_TYPE_REF_24,
+ USB_CLOCK_TYPE_REF_48,
+ USB_CLOCK_TYPE_CRYSTAL_12,
+};
+
typedef enum {
set_phy_link_flags_autoneg = 0x1,
set_phy_link_flags_flow_control_dont_touch = 0x0 << 1,
@@ -154,4 +161,6 @@ extern int __cvmx_helper_board_interface_probe(int interface,
*/
extern int __cvmx_helper_board_hardware_enable(int interface);
+enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(void);
+
#endif /* __CVMX_HELPER_BOARD_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-pip.h b/arch/mips/include/asm/octeon/cvmx-pip.h
index a76fe5a57a9..df69bfd2b00 100644
--- a/arch/mips/include/asm/octeon/cvmx-pip.h
+++ b/arch/mips/include/asm/octeon/cvmx-pip.h
@@ -192,13 +192,13 @@ typedef struct {
/* Number of packets processed by PIP */
uint32_t packets;
/*
- * Number of indentified L2 multicast packets. Does not
+ * Number of identified L2 multicast packets. Does not
* include broadcast packets. Only includes packets whose
* parse mode is SKIP_TO_L2
*/
uint32_t multicast_packets;
/*
- * Number of indentified L2 broadcast packets. Does not
+ * Number of identified L2 broadcast packets. Does not
* include multicast packets. Only includes packets whose
* parse mode is SKIP_TO_L2
*/
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index f5d77b91537..d781f9e6688 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -211,7 +211,6 @@ union octeon_cvmemctl {
extern void octeon_write_lcd(const char *s);
extern void octeon_check_cpu_bist(void);
-extern int octeon_get_boot_debug_flag(void);
extern int octeon_get_boot_uart(void);
struct uart_port;
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index f6be4741f7e..5699ec3a71a 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -11,6 +11,8 @@
#include <spaces.h>
#include <linux/const.h>
+#include <linux/kernel.h>
+#include <asm/mipsregs.h>
/*
* PAGE_SHIFT determines the page size
@@ -33,6 +35,29 @@
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+/*
+ * This is used for calculating the real page sizes
+ * for FTLB or VTLB + FTLB confugrations.
+ */
+static inline unsigned int page_size_ftlb(unsigned int mmuextdef)
+{
+ switch (mmuextdef) {
+ case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT:
+ if (PAGE_SIZE == (1 << 30))
+ return 5;
+ if (PAGE_SIZE == (1llu << 32))
+ return 6;
+ if (PAGE_SIZE > (256 << 10))
+ return 7; /* reserved */
+ /* fall through */
+ case MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT:
+ return (PAGE_SHIFT - 10) / 2;
+ default:
+ panic("Invalid FTLB configuration with Conf4_mmuextdef=%d value\n",
+ mmuextdef >> 14);
+ }
+}
+
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
#define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
@@ -165,7 +190,9 @@ typedef struct { unsigned long pgprot; } pgprot_t;
* https://patchwork.linux-mips.org/patch/1541/
*/
+#ifndef __pa_symbol
#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
+#endif
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index f194c08bd05..974b0e30896 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -73,16 +73,23 @@ extern unsigned long PCIBIOS_MIN_MEM;
extern void pcibios_set_master(struct pci_dev *dev);
-static inline void pcibios_penalize_isa_irq(int irq, int active)
-{
- /* We don't do dynamic PCI IRQ allocation */
-}
-
#define HAVE_PCI_MMAP
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+
+static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc, resource_size_t *start,
+ resource_size_t *end)
+{
+ phys_t size = resource_size(rsrc);
+
+ *start = fixup_bigphys_addr(rsrc->start, size);
+ *end = rsrc->start + size;
+}
+
/*
* Dynamic DMA mapping stuff.
* MIPS has everything mapped statically.
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
index 881d18b4e29..b336037e876 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -80,9 +80,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
struct page *pte;
pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
- if (pte) {
- clear_highpage(pte);
- pgtable_page_ctor(pte);
+ if (!pte)
+ return NULL;
+ clear_highpage(pte);
+ if (!pgtable_page_ctor(pte)) {
+ __free_page(pte);
+ return NULL;
}
return pte;
}
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h
index 32aea4852fb..e592f3687d6 100644
--- a/arch/mips/include/asm/pgtable-bits.h
+++ b/arch/mips/include/asm/pgtable-bits.h
@@ -235,6 +235,15 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
#define _CACHE_CACHABLE_NONCOHERENT (5<<_CACHE_SHIFT)
#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT)
+#elif defined(CONFIG_CPU_LOONGSON3)
+
+/* Using COHERENT flag for NONCOHERENT doesn't hurt. */
+
+#define _CACHE_UNCACHED (2<<_CACHE_SHIFT) /* LOONGSON */
+#define _CACHE_CACHABLE_NONCOHERENT (3<<_CACHE_SHIFT) /* LOONGSON */
+#define _CACHE_CACHABLE_COHERENT (3<<_CACHE_SHIFT) /* LOONGSON-3 */
+#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT) /* LOONGSON */
+
#else
#define _CACHE_CACHABLE_NO_WA (0<<_CACHE_SHIFT) /* R4600 only */
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 008324d1c26..539ddd148bb 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -32,6 +32,8 @@ struct vm_area_struct;
_page_cachable_default)
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
_PAGE_GLOBAL | _page_cachable_default)
+#define PAGE_KERNEL_NC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
+ _PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT)
#define PAGE_USERIO __pgprot(_PAGE_PRESENT | (cpu_has_rixi ? 0 : _PAGE_READ) | _PAGE_WRITE | \
_page_cachable_default)
#define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \
diff --git a/arch/mips/include/asm/pm-cps.h b/arch/mips/include/asm/pm-cps.h
new file mode 100644
index 00000000000..625eda53d57
--- /dev/null
+++ b/arch/mips/include/asm/pm-cps.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_PM_CPS_H__
+#define __MIPS_ASM_PM_CPS_H__
+
+/*
+ * The CM & CPC can only handle coherence & power control on a per-core basis,
+ * thus in an MT system the VPEs within each core are coupled and can only
+ * enter or exit states requiring CM or CPC assistance in unison.
+ */
+#ifdef CONFIG_MIPS_MT
+# define coupled_coherence cpu_has_mipsmt
+#else
+# define coupled_coherence 0
+#endif
+
+/* Enumeration of possible PM states */
+enum cps_pm_state {
+ CPS_PM_NC_WAIT, /* MIPS wait instruction, non-coherent */
+ CPS_PM_CLOCK_GATED, /* Core clock gated */
+ CPS_PM_POWER_GATED, /* Core power gated */
+ CPS_PM_STATE_COUNT,
+};
+
+/**
+ * cps_pm_support_state - determine whether the system supports a PM state
+ * @state: the state to test for support
+ *
+ * Returns true if the system supports the given state, otherwise false.
+ */
+extern bool cps_pm_support_state(enum cps_pm_state state);
+
+/**
+ * cps_pm_enter_state - enter a PM state
+ * @state: the state to enter
+ *
+ * Enter the given PM state. If coupled_coherence is non-zero then it is
+ * expected that this function be called at approximately the same time on
+ * each coupled CPU. Returns 0 on successful entry & exit, otherwise -errno.
+ */
+extern int cps_pm_enter_state(enum cps_pm_state state);
+
+#endif /* __MIPS_ASM_PM_CPS_H__ */
diff --git a/arch/mips/include/asm/pm.h b/arch/mips/include/asm/pm.h
new file mode 100644
index 00000000000..7c03469e043
--- /dev/null
+++ b/arch/mips/include/asm/pm.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies Ltd
+ *
+ * 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.
+ *
+ * PM helper macros for CPU power off (e.g. Suspend-to-RAM).
+ */
+
+#ifndef __ASM_PM_H
+#define __ASM_PM_H
+
+#ifdef __ASSEMBLY__
+
+#include <asm/asm-offsets.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+/* Save CPU state to stack for suspend to RAM */
+.macro SUSPEND_SAVE_REGS
+ subu sp, PT_SIZE
+ /* Call preserved GPRs */
+ LONG_S $16, PT_R16(sp)
+ LONG_S $17, PT_R17(sp)
+ LONG_S $18, PT_R18(sp)
+ LONG_S $19, PT_R19(sp)
+ LONG_S $20, PT_R20(sp)
+ LONG_S $21, PT_R21(sp)
+ LONG_S $22, PT_R22(sp)
+ LONG_S $23, PT_R23(sp)
+ LONG_S $28, PT_R28(sp)
+ LONG_S $30, PT_R30(sp)
+ LONG_S $31, PT_R31(sp)
+ /* A couple of CP0 registers with space in pt_regs */
+ mfc0 k0, CP0_STATUS
+ LONG_S k0, PT_STATUS(sp)
+.endm
+
+/* Restore CPU state from stack after resume from RAM */
+.macro RESUME_RESTORE_REGS_RETURN
+ .set push
+ .set noreorder
+ /* A couple of CP0 registers with space in pt_regs */
+ LONG_L k0, PT_STATUS(sp)
+ mtc0 k0, CP0_STATUS
+ /* Call preserved GPRs */
+ LONG_L $16, PT_R16(sp)
+ LONG_L $17, PT_R17(sp)
+ LONG_L $18, PT_R18(sp)
+ LONG_L $19, PT_R19(sp)
+ LONG_L $20, PT_R20(sp)
+ LONG_L $21, PT_R21(sp)
+ LONG_L $22, PT_R22(sp)
+ LONG_L $23, PT_R23(sp)
+ LONG_L $28, PT_R28(sp)
+ LONG_L $30, PT_R30(sp)
+ LONG_L $31, PT_R31(sp)
+ /* Pop and return */
+ jr ra
+ addiu sp, PT_SIZE
+ .set pop
+.endm
+
+/* Get address of static suspend state into t1 */
+.macro LA_STATIC_SUSPEND
+ la t1, mips_static_suspend_state
+.endm
+
+/* Save important CPU state for early restoration to global data */
+.macro SUSPEND_SAVE_STATIC
+#ifdef CONFIG_EVA
+ /*
+ * Segment configuration is saved in global data where it can be easily
+ * reloaded without depending on the segment configuration.
+ */
+ mfc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
+ LONG_S k0, SSS_SEGCTL0(t1)
+ mfc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
+ LONG_S k0, SSS_SEGCTL1(t1)
+ mfc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
+ LONG_S k0, SSS_SEGCTL2(t1)
+#endif
+ /* save stack pointer (pointing to GPRs) */
+ LONG_S sp, SSS_SP(t1)
+.endm
+
+/* Restore important CPU state early from global data */
+.macro RESUME_RESTORE_STATIC
+#ifdef CONFIG_EVA
+ /*
+ * Segment configuration must be restored prior to any access to
+ * allocated memory, as it may reside outside of the legacy kernel
+ * segments.
+ */
+ LONG_L k0, SSS_SEGCTL0(t1)
+ mtc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
+ LONG_L k0, SSS_SEGCTL1(t1)
+ mtc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
+ LONG_L k0, SSS_SEGCTL2(t1)
+ mtc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
+ tlbw_use_hazard
+#endif
+ /* restore stack pointer (pointing to GPRs) */
+ LONG_L sp, SSS_SP(t1)
+.endm
+
+/* flush caches to make sure context has reached memory */
+.macro SUSPEND_CACHE_FLUSH
+ .extern __wback_cache_all
+ .set push
+ .set noreorder
+ la t1, __wback_cache_all
+ LONG_L t0, 0(t1)
+ jalr t0
+ nop
+ .set pop
+ .endm
+
+/* Save suspend state and flush data caches to RAM */
+.macro SUSPEND_SAVE
+ SUSPEND_SAVE_REGS
+ LA_STATIC_SUSPEND
+ SUSPEND_SAVE_STATIC
+ SUSPEND_CACHE_FLUSH
+.endm
+
+/* Restore saved state after resume from RAM and return */
+.macro RESUME_RESTORE_RETURN
+ LA_STATIC_SUSPEND
+ RESUME_RESTORE_STATIC
+ RESUME_RESTORE_REGS_RETURN
+.endm
+
+#else /* __ASSEMBLY__ */
+
+/**
+ * struct mips_static_suspend_state - Core saved CPU state across S2R.
+ * @segctl: CP0 Segment control registers.
+ * @sp: Stack frame where GP register context is saved.
+ *
+ * This structure contains minimal CPU state that must be saved in static kernel
+ * data in order to be able to restore the rest of the state. This includes
+ * segmentation configuration in the case of EVA being enabled, as they must be
+ * restored prior to any kmalloc'd memory being referenced (even the stack
+ * pointer).
+ */
+struct mips_static_suspend_state {
+#ifdef CONFIG_EVA
+ unsigned long segctl[3];
+#endif
+ unsigned long sp;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __ASM_PM_HELPERS_H */
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 3605b844ad8..ad70cba8daf 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -97,18 +97,48 @@ extern unsigned int vced_count, vcei_count;
#define NUM_FPU_REGS 32
-typedef __u64 fpureg_t;
+#ifdef CONFIG_CPU_HAS_MSA
+# define FPU_REG_WIDTH 128
+#else
+# define FPU_REG_WIDTH 64
+#endif
+
+union fpureg {
+ __u32 val32[FPU_REG_WIDTH / 32];
+ __u64 val64[FPU_REG_WIDTH / 64];
+};
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# define FPR_IDX(width, idx) (idx)
+#else
+# define FPR_IDX(width, idx) ((FPU_REG_WIDTH / (width)) - 1 - (idx))
+#endif
+
+#define BUILD_FPR_ACCESS(width) \
+static inline u##width get_fpr##width(union fpureg *fpr, unsigned idx) \
+{ \
+ return fpr->val##width[FPR_IDX(width, idx)]; \
+} \
+ \
+static inline void set_fpr##width(union fpureg *fpr, unsigned idx, \
+ u##width val) \
+{ \
+ fpr->val##width[FPR_IDX(width, idx)] = val; \
+}
+
+BUILD_FPR_ACCESS(32)
+BUILD_FPR_ACCESS(64)
/*
- * It would be nice to add some more fields for emulator statistics, but there
- * are a number of fixed offsets in offset.h and elsewhere that would have to
- * be recalculated by hand. So the additional information will be private to
- * the FPU emulator for now. See asm-mips/fpu_emulator.h.
+ * It would be nice to add some more fields for emulator statistics,
+ * the additional information is private to the FPU emulator for now.
+ * See arch/mips/include/asm/fpu_emulator.h.
*/
struct mips_fpu_struct {
- fpureg_t fpr[NUM_FPU_REGS];
+ union fpureg fpr[NUM_FPU_REGS];
unsigned int fcr31;
+ unsigned int msacsr;
};
#define NUM_DSP_REGS 6
@@ -284,8 +314,9 @@ struct thread_struct {
* Saved FPU/FPU emulator stuff \
*/ \
.fpu = { \
- .fpr = {0,}, \
+ .fpr = {{{0,},},}, \
.fcr31 = 0, \
+ .msacsr = 0, \
}, \
/* \
* FPU affinity state (null if not FPAFF) \
diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h
index 1e7e0961064..a9494c0141f 100644
--- a/arch/mips/include/asm/prom.h
+++ b/arch/mips/include/asm/prom.h
@@ -17,31 +17,17 @@
#include <linux/types.h>
#include <asm/bootinfo.h>
-extern int early_init_dt_scan_memory_arch(unsigned long node,
- const char *uname, int depth, void *data);
-
extern void device_tree_init(void);
-static inline unsigned long pci_address_to_pio(phys_addr_t address)
-{
- /*
- * The ioport address can be directly used by inX() / outX()
- */
- BUG_ON(address > IO_SPACE_LIMIT);
-
- return (unsigned long) address;
-}
-#define pci_address_to_pio pci_address_to_pio
-
struct boot_param_header;
-extern void __dt_setup_arch(struct boot_param_header *bph);
+extern void __dt_setup_arch(void *bph);
#define dt_setup_arch(sym) \
({ \
- extern struct boot_param_header __dtb_##sym##_begin; \
+ extern char __dtb_##sym##_begin[]; \
\
- __dt_setup_arch(&__dtb_##sym##_begin); \
+ __dt_setup_arch(__dtb_##sym##_begin); \
})
#else /* CONFIG_OF */
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 5e6cd094739..7e6e682aece 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -39,9 +39,6 @@ struct pt_regs {
unsigned long cp0_badvaddr;
unsigned long cp0_cause;
unsigned long cp0_epc;
-#ifdef CONFIG_MIPS_MT_SMTC
- unsigned long cp0_tcstatus;
-#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_CPU_CAVIUM_OCTEON
unsigned long long mpl[3]; /* MTM{0,1,2} */
unsigned long long mtp[3]; /* MTP{0,1,2} */
@@ -81,9 +78,8 @@ static inline long regs_return_value(struct pt_regs *regs)
#define instruction_pointer(regs) ((regs)->cp0_epc)
#define profile_pc(regs) instruction_pointer(regs)
-#define user_stack_pointer(r) ((r)->regs[29])
-extern asmlinkage void syscall_trace_enter(struct pt_regs *regs);
+extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
extern void die(const char *, struct pt_regs *) __noreturn;
@@ -100,4 +96,17 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs)
(struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1; \
})
+/* Helpers for working with the user stack pointer */
+
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+ return regs->regs[29];
+}
+
+static inline void user_stack_pointer_set(struct pt_regs *regs,
+ unsigned long val)
+{
+ regs->regs[29] = val;
+}
+
#endif /* _ASM_PTRACE_H */
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index a0b2650516a..0b8bd28a0df 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -15,7 +15,9 @@
#include <asm/asm.h>
#include <asm/cacheops.h>
#include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
#include <asm/mipsmtregs.h>
+#include <asm/uaccess.h> /* for segment_eq() */
/*
* This macro return a properly sign-extended address suitable as base address
@@ -34,18 +36,17 @@
__asm__ __volatile__( \
" .set push \n" \
" .set noreorder \n" \
- " .set mips3\n\t \n" \
+ " .set arch=r4000 \n" \
" cache %0, %1 \n" \
" .set pop \n" \
: \
: "i" (op), "R" (*(unsigned char *)(addr)))
#ifdef CONFIG_MIPS_MT
+
/*
- * Temporary hacks for SMTC debug. Optionally force single-threaded
- * execution during I-cache flushes.
+ * Optionally force single-threaded execution during I-cache flushes.
*/
-
#define PROTECT_CACHE_FLUSHES 1
#ifdef PROTECT_CACHE_FLUSHES
@@ -162,7 +163,15 @@ static inline void flush_scache_line_indexed(unsigned long addr)
static inline void flush_icache_line(unsigned long addr)
{
__iflush_prologue
- cache_op(Hit_Invalidate_I, addr);
+ switch (boot_cpu_type()) {
+ case CPU_LOONGSON2:
+ cache_op(Hit_Invalidate_I_Loongson2, addr);
+ break;
+
+ default:
+ cache_op(Hit_Invalidate_I, addr);
+ break;
+ }
__iflush_epilogue
}
@@ -194,7 +203,7 @@ static inline void flush_scache_line(unsigned long addr)
__asm__ __volatile__( \
" .set push \n" \
" .set noreorder \n" \
- " .set mips3 \n" \
+ " .set arch=r4000 \n" \
"1: cache %0, (%1) \n" \
"2: .set pop \n" \
" .section __ex_table,\"a\" \n" \
@@ -203,12 +212,38 @@ static inline void flush_scache_line(unsigned long addr)
: \
: "i" (op), "r" (addr))
+#define protected_cachee_op(op,addr) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noreorder \n" \
+ " .set mips0 \n" \
+ " .set eva \n" \
+ "1: cachee %0, (%1) \n" \
+ "2: .set pop \n" \
+ " .section __ex_table,\"a\" \n" \
+ " "STR(PTR)" 1b, 2b \n" \
+ " .previous" \
+ : \
+ : "i" (op), "r" (addr))
+
/*
* The next two are for badland addresses like signal trampolines.
*/
static inline void protected_flush_icache_line(unsigned long addr)
{
- protected_cache_op(Hit_Invalidate_I, addr);
+ switch (boot_cpu_type()) {
+ case CPU_LOONGSON2:
+ protected_cache_op(Hit_Invalidate_I_Loongson2, addr);
+ break;
+
+ default:
+#ifdef CONFIG_EVA
+ protected_cachee_op(Hit_Invalidate_I, addr);
+#else
+ protected_cache_op(Hit_Invalidate_I, addr);
+#endif
+ break;
+ }
}
/*
@@ -339,9 +374,94 @@ static inline void invalidate_tcache_page(unsigned long addr)
: "r" (base), \
"i" (op));
+/*
+ * Perform the cache operation specified by op using a user mode virtual
+ * address while in kernel mode.
+ */
+#define cache16_unroll32_user(base,op) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noreorder \n" \
+ " .set mips0 \n" \
+ " .set eva \n" \
+ " cachee %1, 0x000(%0); cachee %1, 0x010(%0) \n" \
+ " cachee %1, 0x020(%0); cachee %1, 0x030(%0) \n" \
+ " cachee %1, 0x040(%0); cachee %1, 0x050(%0) \n" \
+ " cachee %1, 0x060(%0); cachee %1, 0x070(%0) \n" \
+ " cachee %1, 0x080(%0); cachee %1, 0x090(%0) \n" \
+ " cachee %1, 0x0a0(%0); cachee %1, 0x0b0(%0) \n" \
+ " cachee %1, 0x0c0(%0); cachee %1, 0x0d0(%0) \n" \
+ " cachee %1, 0x0e0(%0); cachee %1, 0x0f0(%0) \n" \
+ " cachee %1, 0x100(%0); cachee %1, 0x110(%0) \n" \
+ " cachee %1, 0x120(%0); cachee %1, 0x130(%0) \n" \
+ " cachee %1, 0x140(%0); cachee %1, 0x150(%0) \n" \
+ " cachee %1, 0x160(%0); cachee %1, 0x170(%0) \n" \
+ " cachee %1, 0x180(%0); cachee %1, 0x190(%0) \n" \
+ " cachee %1, 0x1a0(%0); cachee %1, 0x1b0(%0) \n" \
+ " cachee %1, 0x1c0(%0); cachee %1, 0x1d0(%0) \n" \
+ " cachee %1, 0x1e0(%0); cachee %1, 0x1f0(%0) \n" \
+ " .set pop \n" \
+ : \
+ : "r" (base), \
+ "i" (op));
+
+#define cache32_unroll32_user(base, op) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noreorder \n" \
+ " .set mips0 \n" \
+ " .set eva \n" \
+ " cachee %1, 0x000(%0); cachee %1, 0x020(%0) \n" \
+ " cachee %1, 0x040(%0); cachee %1, 0x060(%0) \n" \
+ " cachee %1, 0x080(%0); cachee %1, 0x0a0(%0) \n" \
+ " cachee %1, 0x0c0(%0); cachee %1, 0x0e0(%0) \n" \
+ " cachee %1, 0x100(%0); cachee %1, 0x120(%0) \n" \
+ " cachee %1, 0x140(%0); cachee %1, 0x160(%0) \n" \
+ " cachee %1, 0x180(%0); cachee %1, 0x1a0(%0) \n" \
+ " cachee %1, 0x1c0(%0); cachee %1, 0x1e0(%0) \n" \
+ " cachee %1, 0x200(%0); cachee %1, 0x220(%0) \n" \
+ " cachee %1, 0x240(%0); cachee %1, 0x260(%0) \n" \
+ " cachee %1, 0x280(%0); cachee %1, 0x2a0(%0) \n" \
+ " cachee %1, 0x2c0(%0); cachee %1, 0x2e0(%0) \n" \
+ " cachee %1, 0x300(%0); cachee %1, 0x320(%0) \n" \
+ " cachee %1, 0x340(%0); cachee %1, 0x360(%0) \n" \
+ " cachee %1, 0x380(%0); cachee %1, 0x3a0(%0) \n" \
+ " cachee %1, 0x3c0(%0); cachee %1, 0x3e0(%0) \n" \
+ " .set pop \n" \
+ : \
+ : "r" (base), \
+ "i" (op));
+
+#define cache64_unroll32_user(base, op) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set noreorder \n" \
+ " .set mips0 \n" \
+ " .set eva \n" \
+ " cachee %1, 0x000(%0); cachee %1, 0x040(%0) \n" \
+ " cachee %1, 0x080(%0); cachee %1, 0x0c0(%0) \n" \
+ " cachee %1, 0x100(%0); cachee %1, 0x140(%0) \n" \
+ " cachee %1, 0x180(%0); cachee %1, 0x1c0(%0) \n" \
+ " cachee %1, 0x200(%0); cachee %1, 0x240(%0) \n" \
+ " cachee %1, 0x280(%0); cachee %1, 0x2c0(%0) \n" \
+ " cachee %1, 0x300(%0); cachee %1, 0x340(%0) \n" \
+ " cachee %1, 0x380(%0); cachee %1, 0x3c0(%0) \n" \
+ " cachee %1, 0x400(%0); cachee %1, 0x440(%0) \n" \
+ " cachee %1, 0x480(%0); cachee %1, 0x4c0(%0) \n" \
+ " cachee %1, 0x500(%0); cachee %1, 0x540(%0) \n" \
+ " cachee %1, 0x580(%0); cachee %1, 0x5c0(%0) \n" \
+ " cachee %1, 0x600(%0); cachee %1, 0x640(%0) \n" \
+ " cachee %1, 0x680(%0); cachee %1, 0x6c0(%0) \n" \
+ " cachee %1, 0x700(%0); cachee %1, 0x740(%0) \n" \
+ " cachee %1, 0x780(%0); cachee %1, 0x7c0(%0) \n" \
+ " .set pop \n" \
+ : \
+ : "r" (base), \
+ "i" (op));
+
/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
-static inline void blast_##pfx##cache##lsize(void) \
+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \
+static inline void extra##blast_##pfx##cache##lsize(void) \
{ \
unsigned long start = INDEX_BASE; \
unsigned long end = start + current_cpu_data.desc.waysize; \
@@ -359,7 +479,7 @@ static inline void blast_##pfx##cache##lsize(void) \
__##pfx##flush_epilogue \
} \
\
-static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
{ \
unsigned long start = page; \
unsigned long end = page + PAGE_SIZE; \
@@ -374,7 +494,7 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
__##pfx##flush_epilogue \
} \
\
-static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
{ \
unsigned long indexmask = current_cpu_data.desc.waysize - 1; \
unsigned long start = INDEX_BASE + (page & indexmask); \
@@ -393,27 +513,56 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
__##pfx##flush_epilogue \
}
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
-
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
+
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
+
+#define __BUILD_BLAST_USER_CACHE(pfx, desc, indexop, hitop, lsize) \
+static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \
+{ \
+ unsigned long start = page; \
+ unsigned long end = page + PAGE_SIZE; \
+ \
+ __##pfx##flush_prologue \
+ \
+ do { \
+ cache##lsize##_unroll32_user(start, hitop); \
+ start += lsize * 32; \
+ } while (start < end); \
+ \
+ __##pfx##flush_epilogue \
+}
+
+__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D,
+ 16)
+__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
+__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D,
+ 32)
+__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
+__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D,
+ 64)
+__BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
/* build blast_xxx_range, protected_blast_xxx_range */
-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
-static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
+#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \
+static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \
unsigned long end) \
{ \
unsigned long lsize = cpu_##desc##_line_size(); \
@@ -432,13 +581,54 @@ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
__##pfx##flush_epilogue \
}
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
+#ifndef CONFIG_EVA
+
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
+
+#else
+
+#define __BUILD_PROT_BLAST_CACHE_RANGE(pfx, desc, hitop) \
+static inline void protected_blast_##pfx##cache##_range(unsigned long start,\
+ unsigned long end) \
+{ \
+ unsigned long lsize = cpu_##desc##_line_size(); \
+ unsigned long addr = start & ~(lsize - 1); \
+ unsigned long aend = (end - 1) & ~(lsize - 1); \
+ \
+ __##pfx##flush_prologue \
+ \
+ if (segment_eq(get_fs(), USER_DS)) { \
+ while (1) { \
+ protected_cachee_op(hitop, addr); \
+ if (addr == aend) \
+ break; \
+ addr += lsize; \
+ } \
+ } else { \
+ while (1) { \
+ protected_cache_op(hitop, addr); \
+ if (addr == aend) \
+ break; \
+ addr += lsize; \
+ } \
+ \
+ } \
+ __##pfx##flush_epilogue \
+}
+
+__BUILD_PROT_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D)
+__BUILD_PROT_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I)
+
+#endif
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
+ protected_, loongson2_)
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , )
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
/* blast_inv_dcache_range */
-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
+__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
+__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
#endif /* _ASM_R4KCACHE_H */
diff --git a/arch/mips/include/asm/rm9k-ocd.h b/arch/mips/include/asm/rm9k-ocd.h
deleted file mode 100644
index b0b80d9ecf9..00000000000
--- a/arch/mips/include/asm/rm9k-ocd.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2004 by Basler Vision Technologies AG
- * Author: Thomas Koeller <thomas.koeller@baslerweb.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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#if !defined(_ASM_RM9K_OCD_H)
-#define _ASM_RM9K_OCD_H
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-
-extern volatile void __iomem * const ocd_base;
-extern volatile void __iomem * const titan_base;
-
-#define ocd_addr(__x__) (ocd_base + (__x__))
-#define titan_addr(__x__) (titan_base + (__x__))
-#define scram_addr(__x__) (scram_base + (__x__))
-
-/* OCD register access */
-#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__))
-#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__))
-#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__))
-#define ocd_writel(__val__, __offs__) \
- __raw_writel((__val__), ocd_addr(__offs__))
-#define ocd_writew(__val__, __offs__) \
- __raw_writew((__val__), ocd_addr(__offs__))
-#define ocd_writeb(__val__, __offs__) \
- __raw_writeb((__val__), ocd_addr(__offs__))
-
-/* TITAN register access - 32 bit-wide only */
-#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__))
-#define titan_writel(__val__, __offs__) \
- __raw_writel((__val__), titan_addr(__offs__))
-
-/* Protect access to shared TITAN registers */
-extern spinlock_t titan_lock;
-extern int titan_irqflags;
-#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags)
-#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags)
-
-#endif /* !defined(_ASM_RM9K_OCD_H) */
diff --git a/arch/mips/include/asm/rtlx.h b/arch/mips/include/asm/rtlx.h
index 90985b61dbd..c1020654876 100644
--- a/arch/mips/include/asm/rtlx.h
+++ b/arch/mips/include/asm/rtlx.h
@@ -1,13 +1,18 @@
/*
- * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
+ * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*/
-
#ifndef __ASM_RTLX_H_
#define __ASM_RTLX_H_
#include <irq.h>
+#define RTLX_MODULE_NAME "rtlx"
+
#define LX_NODE_BASE 10
#define MIPS_CPU_RTLX_IRQ 0
@@ -15,18 +20,31 @@
#define RTLX_VERSION 2
#define RTLX_xID 0x12345600
#define RTLX_ID (RTLX_xID | RTLX_VERSION)
+#define RTLX_BUFFER_SIZE 2048
#define RTLX_CHANNELS 8
#define RTLX_CHANNEL_STDIO 0
#define RTLX_CHANNEL_DBG 1
#define RTLX_CHANNEL_SYSIO 2
-extern int rtlx_open(int index, int can_sleep);
-extern int rtlx_release(int index);
-extern ssize_t rtlx_read(int index, void __user *buff, size_t count);
-extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count);
-extern unsigned int rtlx_read_poll(int index, int can_sleep);
-extern unsigned int rtlx_write_poll(int index);
+void rtlx_starting(int vpe);
+void rtlx_stopping(int vpe);
+
+int rtlx_open(int index, int can_sleep);
+int rtlx_release(int index);
+ssize_t rtlx_read(int index, void __user *buff, size_t count);
+ssize_t rtlx_write(int index, const void __user *buffer, size_t count);
+unsigned int rtlx_read_poll(int index, int can_sleep);
+unsigned int rtlx_write_poll(int index);
+
+int __init rtlx_module_init(void);
+void __exit rtlx_module_exit(void);
+
+void _interrupt_sp(void);
+
+extern struct vpe_notifications rtlx_notify;
+extern const struct file_operations rtlx_fops;
+extern void (*aprp_hook)(void);
enum rtlx_state {
RTLX_STATE_UNUSED = 0,
@@ -35,10 +53,15 @@ enum rtlx_state {
RTLX_STATE_OPENED
};
-#define RTLX_BUFFER_SIZE 2048
+extern struct chan_waitqueues {
+ wait_queue_head_t rt_queue;
+ wait_queue_head_t lx_queue;
+ atomic_t in_open;
+ struct mutex mutex;
+} channel_wqs[RTLX_CHANNELS];
/* each channel supports read and write.
- linux (vpe0) reads lx_buffer and writes rt_buffer
+ linux (vpe0) reads lx_buffer and writes rt_buffer
SP (vpe1) reads rt_buffer and writes lx_buffer
*/
struct rtlx_channel {
@@ -55,11 +78,11 @@ struct rtlx_channel {
char *lx_buffer;
};
-struct rtlx_info {
+extern struct rtlx_info {
unsigned long id;
enum rtlx_state state;
+ int ap_int_pending; /* Status of 0 or 1 for CONFIG_MIPS_CMP only */
struct rtlx_channel channel[RTLX_CHANNELS];
-};
-
+} *rtlx;
#endif /* __ASM_RTLX_H_ */
diff --git a/arch/mips/include/asm/setup.h b/arch/mips/include/asm/setup.h
index e26589ef36e..d7bfdeba9e8 100644
--- a/arch/mips/include/asm/setup.h
+++ b/arch/mips/include/asm/setup.h
@@ -5,6 +5,14 @@
extern void setup_early_printk(void);
+#ifdef CONFIG_EARLY_PRINTK_8250
+extern void setup_8250_early_printk_port(unsigned long base,
+ unsigned int reg_shift, unsigned int timeout);
+#else
+static inline void setup_8250_early_printk_port(unsigned long base,
+ unsigned int reg_shift, unsigned int timeout) {}
+#endif
+
extern void set_handler(unsigned long offset, void *addr, unsigned long len);
extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
diff --git a/arch/mips/include/asm/sgi/ip22.h b/arch/mips/include/asm/sgi/ip22.h
index 8db1a3588cf..87ec9eaa04e 100644
--- a/arch/mips/include/asm/sgi/ip22.h
+++ b/arch/mips/include/asm/sgi/ip22.h
@@ -69,6 +69,8 @@
#define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */
#define SGI_KEYBD_IRQ SGINT_LOCAL2 + 4 /* keyboard */
#define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */
+#define SGI_GIOEXP0_IRQ (SGINT_LOCAL2 + 6) /* Indy GIO EXP0 */
+#define SGI_GIOEXP1_IRQ (SGINT_LOCAL2 + 7) /* Indy GIO EXP1 */
#define ip22_is_fullhouse() (sgioc->sysid & SGIOC_SYSID_FULLHOUSE)
diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h
new file mode 100644
index 00000000000..a06a08a9afc
--- /dev/null
+++ b/arch/mips/include/asm/smp-cps.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_SMP_CPS_H__
+#define __MIPS_ASM_SMP_CPS_H__
+
+#ifndef __ASSEMBLY__
+
+struct vpe_boot_config {
+ unsigned long pc;
+ unsigned long sp;
+ unsigned long gp;
+};
+
+struct core_boot_config {
+ atomic_t vpe_mask;
+ struct vpe_boot_config *vpe_config;
+};
+
+extern struct core_boot_config *mips_cps_core_bootcfg;
+
+extern void mips_cps_core_entry(void);
+extern void mips_cps_core_init(void);
+
+extern struct vpe_boot_config *mips_cps_boot_vpes(void);
+
+extern bool mips_cps_smp_in_use(void);
+
+extern void mips_cps_pm_save(void);
+extern void mips_cps_pm_restore(void);
+
+#else /* __ASSEMBLY__ */
+
+.extern mips_cps_bootcfg;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __MIPS_ASM_SMP_CPS_H__ */
diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index ef2a8041e78..6ba1fb8b11e 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -13,6 +13,8 @@
#include <linux/errno.h>
+#include <asm/mips-cm.h>
+
#ifdef CONFIG_SMP
#include <linux/cpumask.h>
@@ -24,7 +26,6 @@ struct plat_smp_ops {
void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
void (*init_secondary)(void);
void (*smp_finish)(void);
- void (*cpus_done)(void);
void (*boot_secondary)(int cpu, struct task_struct *idle);
void (*smp_setup)(void);
void (*prepare_cpus)(unsigned int max_cpus);
@@ -43,6 +44,9 @@ static inline void plat_smp_setup(void)
mp_ops->smp_setup();
}
+extern void gic_send_ipi_single(int cpu, unsigned int action);
+extern void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action);
+
#else /* !CONFIG_SMP */
struct plat_smp_ops;
@@ -76,6 +80,9 @@ static inline int register_cmp_smp_ops(void)
#ifdef CONFIG_MIPS_CMP
extern struct plat_smp_ops cmp_smp_ops;
+ if (!mips_cm_present())
+ return -ENODEV;
+
register_smp_ops(&cmp_smp_ops);
return 0;
@@ -97,4 +104,13 @@ static inline int register_vsmp_smp_ops(void)
#endif
}
+#ifdef CONFIG_MIPS_CPS
+extern int register_cps_smp_ops(void);
+#else
+static inline int register_cps_smp_ops(void)
+{
+ return -ENODEV;
+}
+#endif
+
#endif /* __ASM_SMP_OPS_H */
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index eb600875848..b037334fca2 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -42,9 +42,13 @@ extern int __cpu_logical_map[NR_CPUS];
#define SMP_ICACHE_FLUSH 0x4
/* Used by kexec crashdump to save all cpu's state */
#define SMP_DUMP 0x8
+#define SMP_ASK_C0COUNT 0x10
extern volatile cpumask_t cpu_callin_map;
+/* Mask of CPUs which are currently definitely operating coherently */
+extern cpumask_t cpu_coherent_mask;
+
extern void asmlinkage smp_bootstrap(void);
/*
diff --git a/arch/mips/include/asm/smtc.h b/arch/mips/include/asm/smtc.h
deleted file mode 100644
index e56b439b787..00000000000
--- a/arch/mips/include/asm/smtc.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _ASM_SMTC_MT_H
-#define _ASM_SMTC_MT_H
-
-/*
- * Definitions for SMTC multitasking on MIPS MT cores
- */
-
-#include <asm/mips_mt.h>
-#include <asm/smtc_ipi.h>
-
-/*
- * System-wide SMTC status information
- */
-
-extern unsigned int smtc_status;
-
-#define SMTC_TLB_SHARED 0x00000001
-#define SMTC_MTC_ACTIVE 0x00000002
-
-/*
- * TLB/ASID Management information
- */
-
-#define MAX_SMTC_TLBS 2
-#define MAX_SMTC_ASIDS 256
-#if NR_CPUS <= 8
-typedef char asiduse;
-#else
-#if NR_CPUS <= 16
-typedef short asiduse;
-#else
-typedef long asiduse;
-#endif
-#endif
-
-/*
- * VPE Management information
- */
-
-#define MAX_SMTC_VPES MAX_SMTC_TLBS /* FIXME: May not always be true. */
-
-extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
-
-struct mm_struct;
-struct task_struct;
-
-void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
-void self_ipi(struct smtc_ipi *);
-void smtc_flush_tlb_asid(unsigned long asid);
-extern int smtc_build_cpu_map(int startslot);
-extern void smtc_prepare_cpus(int cpus);
-extern void smtc_smp_finish(void);
-extern void smtc_boot_secondary(int cpu, struct task_struct *t);
-extern void smtc_cpus_done(void);
-extern void smtc_init_secondary(void);
-
-
-/*
- * Sharing the TLB between multiple VPEs means that the
- * "random" index selection function is not allowed to
- * select the current value of the Index register. To
- * avoid additional TLB pressure, the Index registers
- * are "parked" with an non-Valid value.
- */
-
-#define PARKED_INDEX ((unsigned int)0x80000000)
-
-/*
- * Define low-level interrupt mask for IPIs, if necessary.
- * By default, use SW interrupt 1, which requires no external
- * hardware support, but which works only for single-core
- * MIPS MT systems.
- */
-#ifndef MIPS_CPU_IPI_IRQ
-#define MIPS_CPU_IPI_IRQ 1
-#endif
-
-#endif /* _ASM_SMTC_MT_H */
diff --git a/arch/mips/include/asm/smtc_ipi.h b/arch/mips/include/asm/smtc_ipi.h
deleted file mode 100644
index 15278dbd7e7..00000000000
--- a/arch/mips/include/asm/smtc_ipi.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code.
- */
-#ifndef __ASM_SMTC_IPI_H
-#define __ASM_SMTC_IPI_H
-
-#include <linux/spinlock.h>
-
-//#define SMTC_IPI_DEBUG
-
-#ifdef SMTC_IPI_DEBUG
-#include <asm/mipsregs.h>
-#include <asm/mipsmtregs.h>
-#endif /* SMTC_IPI_DEBUG */
-
-/*
- * An IPI "message"
- */
-
-struct smtc_ipi {
- struct smtc_ipi *flink;
- int type;
- void *arg;
- int dest;
-#ifdef SMTC_IPI_DEBUG
- int sender;
- long stamp;
-#endif /* SMTC_IPI_DEBUG */
-};
-
-/*
- * Defined IPI Types
- */
-
-#define LINUX_SMP_IPI 1
-#define SMTC_CLOCK_TICK 2
-#define IRQ_AFFINITY_IPI 3
-
-/*
- * A queue of IPI messages
- */
-
-struct smtc_ipi_q {
- struct smtc_ipi *head;
- spinlock_t lock;
- struct smtc_ipi *tail;
- int depth;
- int resched_flag; /* reschedule already queued */
-};
-
-static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&q->lock, flags);
- if (q->head == NULL)
- q->head = q->tail = p;
- else
- q->tail->flink = p;
- p->flink = NULL;
- q->tail = p;
- q->depth++;
-#ifdef SMTC_IPI_DEBUG
- p->sender = read_c0_tcbind();
- p->stamp = read_c0_count();
-#endif /* SMTC_IPI_DEBUG */
- spin_unlock_irqrestore(&q->lock, flags);
-}
-
-static inline struct smtc_ipi *__smtc_ipi_dq(struct smtc_ipi_q *q)
-{
- struct smtc_ipi *p;
-
- if (q->head == NULL)
- p = NULL;
- else {
- p = q->head;
- q->head = q->head->flink;
- q->depth--;
- /* Arguably unnecessary, but leaves queue cleaner */
- if (q->head == NULL)
- q->tail = NULL;
- }
-
- return p;
-}
-
-static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
-{
- unsigned long flags;
- struct smtc_ipi *p;
-
- spin_lock_irqsave(&q->lock, flags);
- p = __smtc_ipi_dq(q);
- spin_unlock_irqrestore(&q->lock, flags);
-
- return p;
-}
-
-static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&q->lock, flags);
- if (q->head == NULL) {
- q->head = q->tail = p;
- p->flink = NULL;
- } else {
- p->flink = q->head;
- q->head = p;
- }
- q->depth++;
- spin_unlock_irqrestore(&q->lock, flags);
-}
-
-static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
-{
- unsigned long flags;
- int retval;
-
- spin_lock_irqsave(&q->lock, flags);
- retval = q->depth;
- spin_unlock_irqrestore(&q->lock, flags);
- return retval;
-}
-
-extern void smtc_send_ipi(int cpu, int type, unsigned int action);
-
-#endif /* __ASM_SMTC_IPI_H */
diff --git a/arch/mips/include/asm/smtc_proc.h b/arch/mips/include/asm/smtc_proc.h
deleted file mode 100644
index 25da651f1f5..00000000000
--- a/arch/mips/include/asm/smtc_proc.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Definitions for SMTC /proc entries
- * Copyright(C) 2005 MIPS Technologies Inc.
- */
-#ifndef __ASM_SMTC_PROC_H
-#define __ASM_SMTC_PROC_H
-
-/*
- * per-"CPU" statistics
- */
-
-struct smtc_cpu_proc {
- unsigned long timerints;
- unsigned long selfipis;
-};
-
-extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
-
-/* Count of number of recoveries of "stolen" FPU access rights on 34K */
-
-extern atomic_t smtc_fpu_recoveries;
-
-#endif /* __ASM_SMTC_PROC_H */
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 23fc95e6567..b188c797565 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -17,23 +17,14 @@
#include <asm/asmmacro.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
-/*
- * For SMTC kernel, global IE should be left set, and interrupts
- * controlled exclusively via IXMT.
- */
-#ifdef CONFIG_MIPS_MT_SMTC
-#define STATMASK 0x1e
-#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
#define STATMASK 0x3f
#else
#define STATMASK 0x1f
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/mipsmtregs.h>
-#endif /* CONFIG_MIPS_MT_SMTC */
-
.macro SAVE_AT
.set push
.set noat
@@ -93,21 +84,8 @@
.endm
#ifdef CONFIG_SMP
-#ifdef CONFIG_MIPS_MT_SMTC
-#define PTEBASE_SHIFT 19 /* TCBIND */
-#define CPU_ID_REG CP0_TCBIND
-#define CPU_ID_MFC0 mfc0
-#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
-#define PTEBASE_SHIFT 48 /* XCONTEXT */
-#define CPU_ID_REG CP0_XCONTEXT
-#define CPU_ID_MFC0 MFC0
-#else
-#define PTEBASE_SHIFT 23 /* CONTEXT */
-#define CPU_ID_REG CP0_CONTEXT
-#define CPU_ID_MFC0 MFC0
-#endif
.macro get_saved_sp /* SMP variation */
- CPU_ID_MFC0 k0, CPU_ID_REG
+ ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
lui k1, %hi(kernelsp)
#else
@@ -117,17 +95,17 @@
daddiu k1, %hi(kernelsp)
dsll k1, 16
#endif
- LONG_SRL k0, PTEBASE_SHIFT
+ LONG_SRL k0, SMP_CPUID_PTRSHIFT
LONG_ADDU k1, k0
LONG_L k1, %lo(kernelsp)(k1)
.endm
.macro set_saved_sp stackp temp temp2
- CPU_ID_MFC0 \temp, CPU_ID_REG
- LONG_SRL \temp, PTEBASE_SHIFT
+ ASM_CPUID_MFC0 \temp, ASM_SMP_CPUID_REG
+ LONG_SRL \temp, SMP_CPUID_PTRSHIFT
LONG_S \stackp, kernelsp(\temp)
.endm
-#else
+#else /* !CONFIG_SMP */
.macro get_saved_sp /* Uniprocessor variation */
#ifdef CONFIG_CPU_JUMP_WORKAROUNDS
/*
@@ -198,16 +176,6 @@
mfc0 v1, CP0_STATUS
LONG_S $2, PT_R2(sp)
LONG_S v1, PT_STATUS(sp)
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * Ideally, these instructions would be shuffled in
- * to cover the pipeline delay.
- */
- .set mips32
- mfc0 k0, CP0_TCSTATUS
- .set mips0
- LONG_S k0, PT_TCSTATUS(sp)
-#endif /* CONFIG_MIPS_MT_SMTC */
LONG_S $4, PT_R4(sp)
mfc0 v1, CP0_CAUSE
LONG_S $5, PT_R5(sp)
@@ -333,36 +301,6 @@
.set push
.set reorder
.set noat
-#ifdef CONFIG_MIPS_MT_SMTC
- .set mips32r2
- /*
- * We need to make sure the read-modify-write
- * of Status below isn't perturbed by an interrupt
- * or cross-TC access, so we need to do at least a DMT,
- * protected by an interrupt-inhibit. But setting IXMT
- * also creates a few-cycle window where an IPI could
- * be queued and not be detected before potentially
- * returning to a WAIT or user-mode loop. It must be
- * replayed.
- *
- * We're in the middle of a context switch, and
- * we can't dispatch it directly without trashing
- * some registers, so we'll try to detect this unlikely
- * case and program a software interrupt in the VPE,
- * as would be done for a cross-VPE IPI. To accommodate
- * the handling of that case, we're doing a DVPE instead
- * of just a DMT here to protect against other threads.
- * This is a lot of cruft to cover a tiny window.
- * If you can find a better design, implement it!
- *
- */
- mfc0 v0, CP0_TCSTATUS
- ori v0, TCSTATUS_IXMT
- mtc0 v0, CP0_TCSTATUS
- _ehb
- DVPE 5 # dvpe a1
- jal mips_ihb
-#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 a0, CP0_STATUS
ori a0, STATMASK
xori a0, STATMASK
@@ -374,59 +312,6 @@
and v0, v1
or v0, a0
mtc0 v0, CP0_STATUS
-#ifdef CONFIG_MIPS_MT_SMTC
-/*
- * Only after EXL/ERL have been restored to status can we
- * restore TCStatus.IXMT.
- */
- LONG_L v1, PT_TCSTATUS(sp)
- _ehb
- mfc0 a0, CP0_TCSTATUS
- andi v1, TCSTATUS_IXMT
- bnez v1, 0f
-
-/*
- * We'd like to detect any IPIs queued in the tiny window
- * above and request an software interrupt to service them
- * when we ERET.
- *
- * Computing the offset into the IPIQ array of the executing
- * TC's IPI queue in-line would be tedious. We use part of
- * the TCContext register to hold 16 bits of offset that we
- * can add in-line to find the queue head.
- */
- mfc0 v0, CP0_TCCONTEXT
- la a2, IPIQ
- srl v0, v0, 16
- addu a2, a2, v0
- LONG_L v0, 0(a2)
- beqz v0, 0f
-/*
- * If we have a queue, provoke dispatch within the VPE by setting C_SW1
- */
- mfc0 v0, CP0_CAUSE
- ori v0, v0, C_SW1
- mtc0 v0, CP0_CAUSE
-0:
- /*
- * This test should really never branch but
- * let's be prudent here. Having atomized
- * the shared register modifications, we can
- * now EVPE, and must do so before interrupts
- * are potentially re-enabled.
- */
- andi a1, a1, MVPCONTROL_EVP
- beqz a1, 1f
- evpe
-1:
- /* We know that TCStatua.IXMT should be set from above */
- xori a0, a0, TCSTATUS_IXMT
- or a0, a0, v1
- mtc0 a0, CP0_TCSTATUS
- _ehb
-
- .set mips0
-#endif /* CONFIG_MIPS_MT_SMTC */
LONG_L v1, PT_EPC(sp)
MTC0 v1, CP0_EPC
LONG_L $31, PT_R31(sp)
@@ -447,7 +332,7 @@
.macro RESTORE_SP_AND_RET
LONG_L sp, PT_R29(sp)
- .set mips3
+ .set arch=r4000
eret
.set mips0
.endm
@@ -479,33 +364,11 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro CLI
-#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | STATMASK
or t0, t1
xori t0, STATMASK
mtc0 t0, CP0_STATUS
-#else /* CONFIG_MIPS_MT_SMTC */
- /*
- * For SMTC, we need to set privilege
- * and disable interrupts only for the
- * current TC, using the TCStatus register.
- */
- mfc0 t0, CP0_TCSTATUS
- /* Fortunately CU 0 is in the same place in both registers */
- /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
- li t1, ST0_CU0 | 0x08001c00
- or t0, t1
- /* Clear TKSU, leave IXMT */
- xori t0, 0x00001800
- mtc0 t0, CP0_TCSTATUS
- _ehb
- /* We need to leave the global IE bit set, but clear EXL...*/
- mfc0 t0, CP0_STATUS
- ori t0, ST0_EXL | ST0_ERL
- xori t0, ST0_EXL | ST0_ERL
- mtc0 t0, CP0_STATUS
-#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm
@@ -514,35 +377,11 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro STI
-#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | STATMASK
or t0, t1
xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
-#else /* CONFIG_MIPS_MT_SMTC */
- /*
- * For SMTC, we need to set privilege
- * and enable interrupts only for the
- * current TC, using the TCStatus register.
- */
- _ehb
- mfc0 t0, CP0_TCSTATUS
- /* Fortunately CU 0 is in the same place in both registers */
- /* Set TCU0, TKSU (for later inversion) and IXMT */
- li t1, ST0_CU0 | 0x08001c00
- or t0, t1
- /* Clear TKSU *and* IXMT */
- xori t0, 0x00001c00
- mtc0 t0, CP0_TCSTATUS
- _ehb
- /* We need to leave the global IE bit set, but clear EXL...*/
- mfc0 t0, CP0_STATUS
- ori t0, ST0_EXL
- xori t0, ST0_EXL
- mtc0 t0, CP0_STATUS
- /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */
-#endif /* CONFIG_MIPS_MT_SMTC */
irq_enable_hazard
.endm
@@ -552,32 +391,6 @@
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro KMODE
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * This gets baroque in SMTC. We want to
- * protect the non-atomic clearing of EXL
- * with DMT/EMT, but we don't want to take
- * an interrupt while DMT is still in effect.
- */
-
- /* KMODE gets invoked from both reorder and noreorder code */
- .set push
- .set mips32r2
- .set noreorder
- mfc0 v0, CP0_TCSTATUS
- andi v1, v0, TCSTATUS_IXMT
- ori v0, TCSTATUS_IXMT
- mtc0 v0, CP0_TCSTATUS
- _ehb
- DMT 2 # dmt v0
- /*
- * We don't know a priori if ra is "live"
- */
- move t0, ra
- jal mips_ihb
- nop /* delay slot */
- move ra, t0
-#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | (STATMASK & ~1)
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
@@ -588,25 +401,6 @@
or t0, t1
xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
-#ifdef CONFIG_MIPS_MT_SMTC
- _ehb
- andi v0, v0, VPECONTROL_TE
- beqz v0, 2f
- nop /* delay slot */
- emt
-2:
- mfc0 v0, CP0_TCSTATUS
- /* Clear IXMT, then OR in previous value */
- ori v0, TCSTATUS_IXMT
- xori v0, TCSTATUS_IXMT
- or v0, v1, v0
- mtc0 v0, CP0_TCSTATUS
- /*
- * irq_disable_hazard below should expand to EHB
- * on 24K/34K CPUS
- */
- .set pop
-#endif /* CONFIG_MIPS_MT_SMTC */
irq_disable_hazard
.endm
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index eb0af15ac65..495c1041a2c 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -16,14 +16,29 @@
#include <asm/watch.h>
#include <asm/dsp.h>
#include <asm/cop2.h>
+#include <asm/msa.h>
struct task_struct;
-/*
- * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
+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 void *resume(void *last, void *next, void *next_ti, u32 __usedfpu);
+extern asmlinkage struct task_struct *resume(struct task_struct *prev,
+ struct task_struct *next, struct thread_info *next_ti,
+ s32 fp_save);
extern unsigned int ll_bit;
extern struct task_struct *ll_task;
@@ -67,7 +82,8 @@ do { \
#define switch_to(prev, next, last) \
do { \
- u32 __usedfpu, __c0_stat; \
+ u32 __c0_stat; \
+ s32 __fpsave = FP_SAVE_NONE; \
__mips_mt_fpaff_switch_to(prev); \
if (cpu_has_dsp) \
__save_dsp(prev); \
@@ -80,8 +96,12 @@ do { \
write_c0_status(__c0_stat & ~ST0_CU2); \
} \
__clear_software_ll_bit(); \
- __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU); \
- (last) = resume(prev, next, task_thread_info(next), __usedfpu); \
+ 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); \
+ disable_msa(); \
} while (0)
#define finish_arch_switch(prev) \
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
new file mode 100644
index 00000000000..17960fe7a8c
--- /dev/null
+++ b/arch/mips/include/asm/syscall.h
@@ -0,0 +1,145 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * 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.
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ *
+ * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
+ */
+
+#ifndef __ASM_MIPS_SYSCALL_H
+#define __ASM_MIPS_SYSCALL_H
+
+#include <linux/compiler.h>
+#include <uapi/linux/audit.h>
+#include <linux/elf-em.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/unistd.h>
+
+#ifndef __NR_syscall /* Only defined if _MIPS_SIM == _MIPS_SIM_ABI32 */
+#define __NR_syscall 4000
+#endif
+
+static inline long syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ /* 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))
+ return regs->regs[4];
+ else
+ return regs->regs[2];
+}
+
+static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
+ struct task_struct *task, struct pt_regs *regs, unsigned int n)
+{
+ unsigned long usp __maybe_unused = regs->regs[29];
+
+ switch (n) {
+ case 0: case 1: case 2: case 3:
+ *arg = regs->regs[4 + n];
+
+ return 0;
+
+#ifdef CONFIG_32BIT
+ case 4: case 5: case 6: case 7:
+ return get_user(*arg, (int *)usp + n);
+#endif
+
+#ifdef CONFIG_64BIT
+ case 4: case 5: case 6: case 7:
+#ifdef CONFIG_MIPS32_O32
+ if (test_thread_flag(TIF_32BIT_REGS))
+ return get_user(*arg, (int *)usp + n);
+ else
+#endif
+ *arg = regs->regs[4 + n];
+
+ return 0;
+#endif
+
+ default:
+ BUG();
+ }
+
+ unreachable();
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->regs[2];
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ /* Do nothing */
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+ struct pt_regs *regs,
+ int error, long val)
+{
+ if (error) {
+ regs->regs[2] = -error;
+ regs->regs[7] = -1;
+ } else {
+ regs->regs[2] = val;
+ regs->regs[7] = 0;
+ }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args)
+{
+ int ret;
+ /* 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)) {
+ i++;
+ n++;
+ }
+
+ while (n--)
+ ret |= mips_get_syscall_arg(args++, task, regs, i++);
+
+ /*
+ * No way to communicate an error because this is a void function.
+ */
+#if 0
+ return ret;
+#endif
+}
+
+extern const unsigned long sys_call_table[];
+extern const unsigned long sys32_call_table[];
+extern const unsigned long sysn32_call_table[];
+
+static inline int syscall_get_arch(void)
+{
+ int arch = EM_MIPS;
+#ifdef CONFIG_64BIT
+ if (!test_thread_flag(TIF_32BIT_REGS))
+ arch |= __AUDIT_ARCH_64BIT;
+ if (test_thread_flag(TIF_32BIT_ADDR))
+ arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
+#endif
+#if defined(__LITTLE_ENDIAN)
+ arch |= __AUDIT_ARCH_LE;
+#endif
+ return arch;
+}
+
+#endif /* __ASM_MIPS_SYSCALL_H */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 61215a34acc..7de865805de 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -92,8 +92,6 @@ static inline struct thread_info *current_thread_info(void)
#define STACK_WARN (THREAD_SIZE / 8)
-#define PREEMPT_ACTIVE 0x10000000
-
/*
* thread information flags
* - these are process state flags that various assembly files may need to
@@ -112,10 +110,14 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOHZ 19 /* in adaptive nohz mode */
#define TIF_FIXADE 20 /* Fix address errors in software */
#define TIF_LOGADE 21 /* Log address errors to syslog */
-#define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */
+#define TIF_32BIT_REGS 22 /* 32-bit general purpose registers */
#define TIF_32BIT_ADDR 23 /* 32-bit address space (o32/n32) */
#define TIF_FPUBOUND 24 /* thread bound to FPU-full CPU set */
#define TIF_LOAD_WATCH 25 /* If set, load watch registers */
+#define TIF_SYSCALL_TRACEPOINT 26 /* syscall tracepoint instrumentation */
+#define TIF_32BIT_FPREGS 27 /* 32-bit floating point registers */
+#define TIF_USEDMSA 29 /* MSA has been used this quantum */
+#define TIF_MSA_CTX_LIVE 30 /* MSA context must be preserved */
#define TIF_SYSCALL_TRACE 31 /* syscall trace active */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -132,21 +134,49 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_32BIT_ADDR (1<<TIF_32BIT_ADDR)
#define _TIF_FPUBOUND (1<<TIF_FPUBOUND)
#define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH)
+#define _TIF_32BIT_FPREGS (1<<TIF_32BIT_FPREGS)
+#define _TIF_USEDMSA (1<<TIF_USEDMSA)
+#define _TIF_MSA_CTX_LIVE (1<<TIF_MSA_CTX_LIVE)
+#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_WORK_SYSCALL_ENTRY (_TIF_NOHZ | _TIF_SYSCALL_TRACE | \
- _TIF_SYSCALL_AUDIT)
+ _TIF_SYSCALL_AUDIT | \
+ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
/* work to do in syscall_trace_leave() */
#define _TIF_WORK_SYSCALL_EXIT (_TIF_NOHZ | _TIF_SYSCALL_TRACE | \
- _TIF_SYSCALL_AUDIT)
+ _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_NOHZ | _TIF_WORK_MASK | \
- _TIF_WORK_SYSCALL_EXIT)
+ _TIF_WORK_SYSCALL_EXIT | \
+ _TIF_SYSCALL_TRACEPOINT)
-#endif /* __KERNEL__ */
+/*
+ * We stash processor id into a COP0 register to retrieve it fast
+ * at kernel exception entry.
+ */
+#if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+#define SMP_CPUID_REG 20, 0 /* XCONTEXT */
+#define ASM_SMP_CPUID_REG $20
+#define SMP_CPUID_PTRSHIFT 48
+#else
+#define SMP_CPUID_REG 4, 0 /* CONTEXT */
+#define ASM_SMP_CPUID_REG $4
+#define SMP_CPUID_PTRSHIFT 23
+#endif
+#ifdef CONFIG_64BIT
+#define SMP_CPUID_REGSHIFT (SMP_CPUID_PTRSHIFT + 3)
+#else
+#define SMP_CPUID_REGSHIFT (SMP_CPUID_PTRSHIFT + 2)
+#endif
+
+#define ASM_CPUID_MFC0 MFC0
+#define UASM_i_CPUID_MFC0 UASM_i_MFC0
+
+#endif /* __KERNEL__ */
#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index 2d7b9df4542..8f3047d611e 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -52,14 +52,11 @@ extern int (*perf_irq)(void);
*/
extern unsigned int __weak get_c0_compare_int(void);
extern int r4k_clockevent_init(void);
-extern int smtc_clockevent_init(void);
extern int gic_clockevent_init(void);
static inline int mips_clockevent_init(void)
{
-#ifdef CONFIG_MIPS_MT_SMTC
- return smtc_clockevent_init();
-#elif defined(CONFIG_CEVT_GIC)
+#if defined(CONFIG_CEVT_GIC)
return (gic_clockevent_init() | r4k_clockevent_init());
#elif defined(CONFIG_CEVT_R4K)
return r4k_clockevent_init();
@@ -75,7 +72,7 @@ extern int init_r4k_clocksource(void);
static inline int init_mips_clocksource(void)
{
-#if defined(CONFIG_CSRC_R4K) && !defined(CONFIG_CSRC_GIC)
+#ifdef CONFIG_CSRC_R4K
return init_r4k_clocksource();
#else
return 0;
diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h
index 6529704aa73..b05bb70a2e4 100644
--- a/arch/mips/include/asm/timex.h
+++ b/arch/mips/include/asm/timex.h
@@ -4,13 +4,19 @@
* for more details.
*
* Copyright (C) 1998, 1999, 2003 by Ralf Baechle
+ * Copyright (C) 2014 by Maciej W. Rozycki
*/
#ifndef _ASM_TIMEX_H
#define _ASM_TIMEX_H
#ifdef __KERNEL__
+#include <linux/compiler.h>
+
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
#include <asm/mipsregs.h>
+#include <asm/cpu-type.h>
/*
* This is the clock rate of the i8253 PIT. A MIPS system may not have
@@ -33,10 +39,64 @@
typedef unsigned int cycles_t;
+/*
+ * On R4000/R4400 before version 5.0 an erratum exists such that if the
+ * cycle counter is read in the exact moment that it is matching the
+ * compare register, no interrupt will be generated.
+ *
+ * There is a suggested workaround and also the erratum can't strike if
+ * the compare interrupt isn't being used as the clock source device.
+ * However for now the implementaton of this function doesn't get these
+ * fine details right.
+ */
+static inline int can_use_mips_counter(unsigned int prid)
+{
+ int comp = (prid & PRID_COMP_MASK) != PRID_COMP_LEGACY;
+
+ if (__builtin_constant_p(cpu_has_counter) && !cpu_has_counter)
+ return 0;
+ else if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r)
+ return 1;
+ else if (likely(!__builtin_constant_p(cpu_has_mips_r) && comp))
+ return 1;
+ /* Make sure we don't peek at cpu_data[0].options in the fast path! */
+ if (!__builtin_constant_p(cpu_has_counter))
+ asm volatile("" : "=m" (cpu_data[0].options));
+ if (likely(cpu_has_counter &&
+ prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0))))
+ return 1;
+ else
+ return 0;
+}
+
static inline cycles_t get_cycles(void)
{
- return 0;
+ if (can_use_mips_counter(read_c0_prid()))
+ return read_c0_count();
+ else
+ return 0; /* no usable counter */
+}
+
+/*
+ * Like get_cycles - but where c0_count is not available we desperately
+ * use c0_random in an attempt to get at least a little bit of entropy.
+ *
+ * R6000 and R6000A neither have a count register nor a random register.
+ * That leaves no entropy source in the CPU itself.
+ */
+static inline unsigned long random_get_entropy(void)
+{
+ unsigned int prid = read_c0_prid();
+ unsigned int imp = prid & PRID_IMP_MASK;
+
+ if (can_use_mips_counter(prid))
+ return read_c0_count();
+ else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A))
+ return read_c0_random();
+ else
+ return 0; /* no usable register */
}
+#define random_get_entropy random_get_entropy
#endif /* __KERNEL__ */
diff --git a/arch/mips/include/asm/tlb.h b/arch/mips/include/asm/tlb.h
index c67842bc8ef..4a2349302b5 100644
--- a/arch/mips/include/asm/tlb.h
+++ b/arch/mips/include/asm/tlb.h
@@ -18,6 +18,10 @@
*/
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+#define UNIQUE_ENTRYHI(idx) \
+ ((CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) | \
+ (cpu_has_tlbinv ? MIPS_ENTRYHI_EHINV : 0))
+
#include <asm-generic/tlb.h>
#endif /* __ASM_TLB_H */
diff --git a/arch/mips/include/asm/topology.h b/arch/mips/include/asm/topology.h
index 12609a17dc8..20ea4859c82 100644
--- a/arch/mips/include/asm/topology.h
+++ b/arch/mips/include/asm/topology.h
@@ -10,8 +10,4 @@
#include <topology.h>
-#ifdef CONFIG_SMP
-#define smt_capable() (smp_num_siblings > 1)
-#endif
-
#endif /* __ASM_TOPOLOGY_H */
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index f3fa3750f57..a1095109023 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -6,6 +6,7 @@
* Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
* Copyright (C) 2007 Maciej W. Rozycki
+ * Copyright (C) 2014, Imagination Technologies Ltd.
*/
#ifndef _ASM_UACCESS_H
#define _ASM_UACCESS_H
@@ -13,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/thread_info.h>
+#include <asm/asm-eva.h>
/*
* The fs value determines whether argument validity checking should be
@@ -222,11 +224,44 @@ struct __large_struct { unsigned long buf[100]; };
* Yuck. We need two variants, one for 64bit operation and one
* for 32 bit mode and old iron.
*/
+#ifndef CONFIG_EVA
+#define __get_kernel_common(val, size, ptr) __get_user_common(val, size, ptr)
+#else
+/*
+ * Kernel specific functions for EVA. We need to use normal load instructions
+ * to read data from kernel when operating in EVA mode. We use these macros to
+ * avoid redefining __get_user_asm for EVA.
+ */
+#undef _loadd
+#undef _loadw
+#undef _loadh
+#undef _loadb
#ifdef CONFIG_32BIT
-#define __GET_USER_DW(val, ptr) __get_user_asm_ll32(val, ptr)
+#define _loadd _loadw
+#else
+#define _loadd(reg, addr) "ld " reg ", " addr
+#endif
+#define _loadw(reg, addr) "lw " reg ", " addr
+#define _loadh(reg, addr) "lh " reg ", " addr
+#define _loadb(reg, addr) "lb " reg ", " addr
+
+#define __get_kernel_common(val, size, ptr) \
+do { \
+ switch (size) { \
+ case 1: __get_data_asm(val, _loadb, ptr); break; \
+ case 2: __get_data_asm(val, _loadh, ptr); break; \
+ case 4: __get_data_asm(val, _loadw, ptr); break; \
+ case 8: __GET_DW(val, _loadd, ptr); break; \
+ default: __get_user_unknown(); break; \
+ } \
+} while (0)
+#endif
+
+#ifdef CONFIG_32BIT
+#define __GET_DW(val, insn, ptr) __get_data_asm_ll32(val, insn, ptr)
#endif
#ifdef CONFIG_64BIT
-#define __GET_USER_DW(val, ptr) __get_user_asm(val, "ld", ptr)
+#define __GET_DW(val, insn, ptr) __get_data_asm(val, insn, ptr)
#endif
extern void __get_user_unknown(void);
@@ -234,10 +269,10 @@ extern void __get_user_unknown(void);
#define __get_user_common(val, size, ptr) \
do { \
switch (size) { \
- case 1: __get_user_asm(val, "lb", ptr); break; \
- case 2: __get_user_asm(val, "lh", ptr); break; \
- case 4: __get_user_asm(val, "lw", ptr); break; \
- case 8: __GET_USER_DW(val, ptr); break; \
+ case 1: __get_data_asm(val, user_lb, ptr); break; \
+ case 2: __get_data_asm(val, user_lh, ptr); break; \
+ case 4: __get_data_asm(val, user_lw, ptr); break; \
+ case 8: __GET_DW(val, user_ld, ptr); break; \
default: __get_user_unknown(); break; \
} \
} while (0)
@@ -246,8 +281,12 @@ do { \
({ \
int __gu_err; \
\
- __chk_user_ptr(ptr); \
- __get_user_common((x), size, ptr); \
+ if (segment_eq(get_fs(), get_ds())) { \
+ __get_kernel_common((x), size, ptr); \
+ } else { \
+ __chk_user_ptr(ptr); \
+ __get_user_common((x), size, ptr); \
+ } \
__gu_err; \
})
@@ -257,18 +296,22 @@ do { \
const __typeof__(*(ptr)) __user * __gu_ptr = (ptr); \
\
might_fault(); \
- if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \
- __get_user_common((x), size, __gu_ptr); \
+ if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) { \
+ if (segment_eq(get_fs(), get_ds())) \
+ __get_kernel_common((x), size, __gu_ptr); \
+ else \
+ __get_user_common((x), size, __gu_ptr); \
+ } \
\
__gu_err; \
})
-#define __get_user_asm(val, insn, addr) \
+#define __get_data_asm(val, insn, addr) \
{ \
long __gu_tmp; \
\
__asm__ __volatile__( \
- "1: " insn " %1, %3 \n" \
+ "1: "insn("%1", "%3")" \n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
@@ -287,7 +330,7 @@ do { \
/*
* Get a long long 64 using 32 bit registers.
*/
-#define __get_user_asm_ll32(val, addr) \
+#define __get_data_asm_ll32(val, insn, addr) \
{ \
union { \
unsigned long long l; \
@@ -295,8 +338,8 @@ do { \
} __gu_tmp; \
\
__asm__ __volatile__( \
- "1: lw %1, (%3) \n" \
- "2: lw %D1, 4(%3) \n" \
+ "1: " insn("%1", "(%3)")" \n" \
+ "2: " insn("%D1", "4(%3)")" \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
@@ -315,30 +358,73 @@ do { \
(val) = __gu_tmp.t; \
}
+#ifndef CONFIG_EVA
+#define __put_kernel_common(ptr, size) __put_user_common(ptr, size)
+#else
+/*
+ * Kernel specific functions for EVA. We need to use normal load instructions
+ * to read data from kernel when operating in EVA mode. We use these macros to
+ * avoid redefining __get_data_asm for EVA.
+ */
+#undef _stored
+#undef _storew
+#undef _storeh
+#undef _storeb
+#ifdef CONFIG_32BIT
+#define _stored _storew
+#else
+#define _stored(reg, addr) "ld " reg ", " addr
+#endif
+
+#define _storew(reg, addr) "sw " reg ", " addr
+#define _storeh(reg, addr) "sh " reg ", " addr
+#define _storeb(reg, addr) "sb " reg ", " addr
+
+#define __put_kernel_common(ptr, size) \
+do { \
+ switch (size) { \
+ case 1: __put_data_asm(_storeb, ptr); break; \
+ case 2: __put_data_asm(_storeh, ptr); break; \
+ case 4: __put_data_asm(_storew, ptr); break; \
+ case 8: __PUT_DW(_stored, ptr); break; \
+ default: __put_user_unknown(); break; \
+ } \
+} while(0)
+#endif
+
/*
* Yuck. We need two variants, one for 64bit operation and one
* for 32 bit mode and old iron.
*/
#ifdef CONFIG_32BIT
-#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr)
+#define __PUT_DW(insn, ptr) __put_data_asm_ll32(insn, ptr)
#endif
#ifdef CONFIG_64BIT
-#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
+#define __PUT_DW(insn, ptr) __put_data_asm(insn, ptr)
#endif
+#define __put_user_common(ptr, size) \
+do { \
+ switch (size) { \
+ case 1: __put_data_asm(user_sb, ptr); break; \
+ case 2: __put_data_asm(user_sh, ptr); break; \
+ case 4: __put_data_asm(user_sw, ptr); break; \
+ case 8: __PUT_DW(user_sd, ptr); break; \
+ default: __put_user_unknown(); break; \
+ } \
+} while (0)
+
#define __put_user_nocheck(x, ptr, size) \
({ \
__typeof__(*(ptr)) __pu_val; \
int __pu_err = 0; \
\
- __chk_user_ptr(ptr); \
__pu_val = (x); \
- switch (size) { \
- case 1: __put_user_asm("sb", ptr); break; \
- case 2: __put_user_asm("sh", ptr); break; \
- case 4: __put_user_asm("sw", ptr); break; \
- case 8: __PUT_USER_DW(ptr); break; \
- default: __put_user_unknown(); break; \
+ if (segment_eq(get_fs(), get_ds())) { \
+ __put_kernel_common(ptr, size); \
+ } else { \
+ __chk_user_ptr(ptr); \
+ __put_user_common(ptr, size); \
} \
__pu_err; \
})
@@ -351,21 +437,19 @@ do { \
\
might_fault(); \
if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \
- switch (size) { \
- case 1: __put_user_asm("sb", __pu_addr); break; \
- case 2: __put_user_asm("sh", __pu_addr); break; \
- case 4: __put_user_asm("sw", __pu_addr); break; \
- case 8: __PUT_USER_DW(__pu_addr); break; \
- default: __put_user_unknown(); break; \
- } \
+ if (segment_eq(get_fs(), get_ds())) \
+ __put_kernel_common(__pu_addr, size); \
+ else \
+ __put_user_common(__pu_addr, size); \
} \
+ \
__pu_err; \
})
-#define __put_user_asm(insn, ptr) \
+#define __put_data_asm(insn, ptr) \
{ \
__asm__ __volatile__( \
- "1: " insn " %z2, %3 # __put_user_asm\n" \
+ "1: "insn("%z2", "%3")" # __put_data_asm \n" \
"2: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
@@ -380,11 +464,11 @@ do { \
"i" (-EFAULT)); \
}
-#define __put_user_asm_ll32(ptr) \
+#define __put_data_asm_ll32(insn, ptr) \
{ \
__asm__ __volatile__( \
- "1: sw %2, (%3) # __put_user_asm_ll32 \n" \
- "2: sw %D2, 4(%3) \n" \
+ "1: "insn("%2", "(%3)")" # __put_data_asm_ll32 \n" \
+ "2: "insn("%D2", "4(%3)")" \n" \
"3: \n" \
" .insn \n" \
" .section .fixup,\"ax\" \n" \
@@ -403,6 +487,11 @@ do { \
extern void __put_user_unknown(void);
/*
+ * ul{b,h,w} are macros and there are no equivalent macros for EVA.
+ * EVA unaligned access is handled in the ADE exception handler.
+ */
+#ifndef CONFIG_EVA
+/*
* put_user_unaligned: - Write a simple value into user space.
* @x: Value to copy to user space.
* @ptr: Destination address, in user space.
@@ -504,7 +593,7 @@ extern void __get_user_unaligned_unknown(void);
#define __get_user_unaligned_common(val, size, ptr) \
do { \
switch (size) { \
- case 1: __get_user_asm(val, "lb", ptr); break; \
+ 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 8: __GET_USER_UNALIGNED_DW(val, ptr); break; \
@@ -531,7 +620,7 @@ do { \
__gu_err; \
})
-#define __get_user_unaligned_asm(val, insn, addr) \
+#define __get_data_unaligned_asm(val, insn, addr) \
{ \
long __gu_tmp; \
\
@@ -594,19 +683,23 @@ do { \
#define __PUT_USER_UNALIGNED_DW(ptr) __put_user_unaligned_asm("usd", ptr)
#endif
+#define __put_user_unaligned_common(ptr, size) \
+do { \
+ switch (size) { \
+ case 1: __put_data_asm("sb", ptr); break; \
+ case 2: __put_user_unaligned_asm("ush", ptr); break; \
+ case 4: __put_user_unaligned_asm("usw", ptr); break; \
+ case 8: __PUT_USER_UNALIGNED_DW(ptr); break; \
+ default: __put_user_unaligned_unknown(); break; \
+} while (0)
+
#define __put_user_unaligned_nocheck(x,ptr,size) \
({ \
__typeof__(*(ptr)) __pu_val; \
int __pu_err = 0; \
\
__pu_val = (x); \
- switch (size) { \
- case 1: __put_user_asm("sb", ptr); break; \
- case 2: __put_user_unaligned_asm("ush", ptr); break; \
- case 4: __put_user_unaligned_asm("usw", ptr); break; \
- case 8: __PUT_USER_UNALIGNED_DW(ptr); break; \
- default: __put_user_unaligned_unknown(); break; \
- } \
+ __put_user_unaligned_common(ptr, size); \
__pu_err; \
})
@@ -616,15 +709,9 @@ do { \
__typeof__(*(ptr)) __pu_val = (x); \
int __pu_err = -EFAULT; \
\
- if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \
- switch (size) { \
- case 1: __put_user_asm("sb", __pu_addr); break; \
- case 2: __put_user_unaligned_asm("ush", __pu_addr); break; \
- case 4: __put_user_unaligned_asm("usw", __pu_addr); break; \
- case 8: __PUT_USER_UNALGINED_DW(__pu_addr); break; \
- default: __put_user_unaligned_unknown(); break; \
- } \
- } \
+ if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) \
+ __put_user_unaligned_common(__pu_addr, size); \
+ \
__pu_err; \
})
@@ -669,6 +756,7 @@ do { \
}
extern void __put_user_unaligned_unknown(void);
+#endif
/*
* We're generating jump to subroutines which will be outside the range of
@@ -693,6 +781,7 @@ extern void __put_user_unaligned_unknown(void);
extern size_t __copy_user(void *__to, const void *__from, size_t __n);
+#ifndef CONFIG_EVA
#define __invoke_copy_to_user(to, from, n) \
({ \
register void __user *__cu_to_r __asm__("$4"); \
@@ -711,6 +800,11 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
__cu_len_r; \
})
+#define __invoke_copy_to_kernel(to, from, n) \
+ __invoke_copy_to_user(to, from, n)
+
+#endif
+
/*
* __copy_to_user: - Copy a block of data into user space, with less checking.
* @to: Destination address, in user space.
@@ -735,7 +829,12 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
__cu_from = (from); \
__cu_len = (n); \
might_fault(); \
- __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len); \
+ if (segment_eq(get_fs(), get_ds())) \
+ __cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \
+ __cu_len); \
+ else \
+ __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, \
+ __cu_len); \
__cu_len; \
})
@@ -750,7 +849,12 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len); \
+ if (segment_eq(get_fs(), get_ds())) \
+ __cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \
+ __cu_len); \
+ else \
+ __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, \
+ __cu_len); \
__cu_len; \
})
@@ -763,8 +867,14 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- __cu_len = __invoke_copy_from_user_inatomic(__cu_to, __cu_from, \
- __cu_len); \
+ if (segment_eq(get_fs(), get_ds())) \
+ __cu_len = __invoke_copy_from_kernel_inatomic(__cu_to, \
+ __cu_from,\
+ __cu_len);\
+ else \
+ __cu_len = __invoke_copy_from_user_inatomic(__cu_to, \
+ __cu_from, \
+ __cu_len); \
__cu_len; \
})
@@ -790,14 +900,23 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) { \
- might_fault(); \
- __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, \
- __cu_len); \
+ if (segment_eq(get_fs(), get_ds())) { \
+ __cu_len = __invoke_copy_to_kernel(__cu_to, \
+ __cu_from, \
+ __cu_len); \
+ } else { \
+ if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) { \
+ might_fault(); \
+ __cu_len = __invoke_copy_to_user(__cu_to, \
+ __cu_from, \
+ __cu_len); \
+ } \
} \
__cu_len; \
})
+#ifndef CONFIG_EVA
+
#define __invoke_copy_from_user(to, from, n) \
({ \
register void *__cu_to_r __asm__("$4"); \
@@ -821,6 +940,17 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_len_r; \
})
+#define __invoke_copy_from_kernel(to, from, n) \
+ __invoke_copy_from_user(to, from, n)
+
+/* For userland <-> userland operations */
+#define ___invoke_copy_in_user(to, from, n) \
+ __invoke_copy_from_user(to, from, n)
+
+/* For kernel <-> kernel operations */
+#define ___invoke_copy_in_kernel(to, from, n) \
+ __invoke_copy_from_user(to, from, n)
+
#define __invoke_copy_from_user_inatomic(to, from, n) \
({ \
register void *__cu_to_r __asm__("$4"); \
@@ -844,6 +974,97 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_len_r; \
})
+#define __invoke_copy_from_kernel_inatomic(to, from, n) \
+ __invoke_copy_from_user_inatomic(to, from, n) \
+
+#else
+
+/* EVA specific functions */
+
+extern size_t __copy_user_inatomic_eva(void *__to, const void *__from,
+ size_t __n);
+extern size_t __copy_from_user_eva(void *__to, const void *__from,
+ size_t __n);
+extern size_t __copy_to_user_eva(void *__to, const void *__from,
+ size_t __n);
+extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
+
+#define __invoke_copy_from_user_eva_generic(to, from, n, func_ptr) \
+({ \
+ register void *__cu_to_r __asm__("$4"); \
+ register const void __user *__cu_from_r __asm__("$5"); \
+ register long __cu_len_r __asm__("$6"); \
+ \
+ __cu_to_r = (to); \
+ __cu_from_r = (from); \
+ __cu_len_r = (n); \
+ __asm__ __volatile__( \
+ ".set\tnoreorder\n\t" \
+ __MODULE_JAL(func_ptr) \
+ ".set\tnoat\n\t" \
+ __UA_ADDU "\t$1, %1, %2\n\t" \
+ ".set\tat\n\t" \
+ ".set\treorder" \
+ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \
+ : \
+ : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \
+ DADDI_SCRATCH, "memory"); \
+ __cu_len_r; \
+})
+
+#define __invoke_copy_to_user_eva_generic(to, from, n, func_ptr) \
+({ \
+ register void *__cu_to_r __asm__("$4"); \
+ register const void __user *__cu_from_r __asm__("$5"); \
+ register long __cu_len_r __asm__("$6"); \
+ \
+ __cu_to_r = (to); \
+ __cu_from_r = (from); \
+ __cu_len_r = (n); \
+ __asm__ __volatile__( \
+ __MODULE_JAL(func_ptr) \
+ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \
+ : \
+ : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \
+ DADDI_SCRATCH, "memory"); \
+ __cu_len_r; \
+})
+
+/*
+ * Source or destination address is in userland. We need to go through
+ * the TLB
+ */
+#define __invoke_copy_from_user(to, from, n) \
+ __invoke_copy_from_user_eva_generic(to, from, n, __copy_from_user_eva)
+
+#define __invoke_copy_from_user_inatomic(to, from, n) \
+ __invoke_copy_from_user_eva_generic(to, from, n, \
+ __copy_user_inatomic_eva)
+
+#define __invoke_copy_to_user(to, from, n) \
+ __invoke_copy_to_user_eva_generic(to, from, n, __copy_to_user_eva)
+
+#define ___invoke_copy_in_user(to, from, n) \
+ __invoke_copy_from_user_eva_generic(to, from, n, __copy_in_user_eva)
+
+/*
+ * Source or destination address in the kernel. We are not going through
+ * the TLB
+ */
+#define __invoke_copy_from_kernel(to, from, n) \
+ __invoke_copy_from_user_eva_generic(to, from, n, __copy_user)
+
+#define __invoke_copy_from_kernel_inatomic(to, from, n) \
+ __invoke_copy_from_user_eva_generic(to, from, n, __copy_user_inatomic)
+
+#define __invoke_copy_to_kernel(to, from, n) \
+ __invoke_copy_to_user_eva_generic(to, from, n, __copy_user)
+
+#define ___invoke_copy_in_kernel(to, from, n) \
+ __invoke_copy_from_user_eva_generic(to, from, n, __copy_user)
+
+#endif /* CONFIG_EVA */
+
/*
* __copy_from_user: - Copy a block of data from user space, with less checking.
* @to: Destination address, in kernel space.
@@ -901,10 +1122,17 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (access_ok(VERIFY_READ, __cu_from, __cu_len)) { \
- might_fault(); \
- __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \
- __cu_len); \
+ if (segment_eq(get_fs(), get_ds())) { \
+ __cu_len = __invoke_copy_from_kernel(__cu_to, \
+ __cu_from, \
+ __cu_len); \
+ } else { \
+ if (access_ok(VERIFY_READ, __cu_from, __cu_len)) { \
+ might_fault(); \
+ __cu_len = __invoke_copy_from_user(__cu_to, \
+ __cu_from, \
+ __cu_len); \
+ } \
} \
__cu_len; \
})
@@ -918,9 +1146,14 @@ extern size_t __copy_user_inatomic(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 (segment_eq(get_fs(), get_ds())) { \
+ __cu_len = ___invoke_copy_in_kernel(__cu_to, __cu_from, \
+ __cu_len); \
+ } else { \
+ might_fault(); \
+ __cu_len = ___invoke_copy_in_user(__cu_to, __cu_from, \
+ __cu_len); \
+ } \
__cu_len; \
})
@@ -933,11 +1166,17 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (likely(access_ok(VERIFY_READ, __cu_from, __cu_len) && \
- access_ok(VERIFY_WRITE, __cu_to, __cu_len))) { \
- might_fault(); \
- __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \
- __cu_len); \
+ if (segment_eq(get_fs(), get_ds())) { \
+ __cu_len = ___invoke_copy_in_kernel(__cu_to,__cu_from, \
+ __cu_len); \
+ } else { \
+ if (likely(access_ok(VERIFY_READ, __cu_from, __cu_len) &&\
+ access_ok(VERIFY_WRITE, __cu_to, __cu_len))) {\
+ might_fault(); \
+ __cu_len = ___invoke_copy_in_user(__cu_to, \
+ __cu_from, \
+ __cu_len); \
+ } \
} \
__cu_len; \
})
@@ -1007,16 +1246,28 @@ __strncpy_from_user(char *__to, const char __user *__from, long __len)
{
long res;
- might_fault();
- __asm__ __volatile__(
- "move\t$4, %1\n\t"
- "move\t$5, %2\n\t"
- "move\t$6, %3\n\t"
- __MODULE_JAL(__strncpy_from_user_nocheck_asm)
- "move\t%0, $2"
- : "=r" (res)
- : "r" (__to), "r" (__from), "r" (__len)
- : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+ if (segment_eq(get_fs(), get_ds())) {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ "move\t$6, %3\n\t"
+ __MODULE_JAL(__strncpy_from_kernel_nocheck_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (__to), "r" (__from), "r" (__len)
+ : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+ } else {
+ might_fault();
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ "move\t$6, %3\n\t"
+ __MODULE_JAL(__strncpy_from_user_nocheck_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (__to), "r" (__from), "r" (__len)
+ : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+ }
return res;
}
@@ -1044,16 +1295,28 @@ strncpy_from_user(char *__to, const char __user *__from, long __len)
{
long res;
- might_fault();
- __asm__ __volatile__(
- "move\t$4, %1\n\t"
- "move\t$5, %2\n\t"
- "move\t$6, %3\n\t"
- __MODULE_JAL(__strncpy_from_user_asm)
- "move\t%0, $2"
- : "=r" (res)
- : "r" (__to), "r" (__from), "r" (__len)
- : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+ if (segment_eq(get_fs(), get_ds())) {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ "move\t$6, %3\n\t"
+ __MODULE_JAL(__strncpy_from_kernel_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (__to), "r" (__from), "r" (__len)
+ : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+ } else {
+ might_fault();
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ "move\t$6, %3\n\t"
+ __MODULE_JAL(__strncpy_from_user_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (__to), "r" (__from), "r" (__len)
+ : "$2", "$3", "$4", "$5", "$6", __UA_t0, "$31", "memory");
+ }
return res;
}
@@ -1063,14 +1326,24 @@ static inline long __strlen_user(const char __user *s)
{
long res;
- might_fault();
- __asm__ __volatile__(
- "move\t$4, %1\n\t"
- __MODULE_JAL(__strlen_user_nocheck_asm)
- "move\t%0, $2"
- : "=r" (res)
- : "r" (s)
- : "$2", "$4", __UA_t0, "$31");
+ if (segment_eq(get_fs(), get_ds())) {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ __MODULE_JAL(__strlen_kernel_nocheck_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s)
+ : "$2", "$4", __UA_t0, "$31");
+ } else {
+ might_fault();
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ __MODULE_JAL(__strlen_user_nocheck_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s)
+ : "$2", "$4", __UA_t0, "$31");
+ }
return res;
}
@@ -1093,14 +1366,24 @@ static inline long strlen_user(const char __user *s)
{
long res;
- might_fault();
- __asm__ __volatile__(
- "move\t$4, %1\n\t"
- __MODULE_JAL(__strlen_user_asm)
- "move\t%0, $2"
- : "=r" (res)
- : "r" (s)
- : "$2", "$4", __UA_t0, "$31");
+ if (segment_eq(get_fs(), get_ds())) {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ __MODULE_JAL(__strlen_kernel_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s)
+ : "$2", "$4", __UA_t0, "$31");
+ } else {
+ might_fault();
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ __MODULE_JAL(__strlen_kernel_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s)
+ : "$2", "$4", __UA_t0, "$31");
+ }
return res;
}
@@ -1110,15 +1393,26 @@ static inline long __strnlen_user(const char __user *s, long n)
{
long res;
- might_fault();
- __asm__ __volatile__(
- "move\t$4, %1\n\t"
- "move\t$5, %2\n\t"
- __MODULE_JAL(__strnlen_user_nocheck_asm)
- "move\t%0, $2"
- : "=r" (res)
- : "r" (s), "r" (n)
- : "$2", "$4", "$5", __UA_t0, "$31");
+ if (segment_eq(get_fs(), get_ds())) {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ __MODULE_JAL(__strnlen_kernel_nocheck_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s), "r" (n)
+ : "$2", "$4", "$5", __UA_t0, "$31");
+ } else {
+ might_fault();
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ __MODULE_JAL(__strnlen_user_nocheck_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s), "r" (n)
+ : "$2", "$4", "$5", __UA_t0, "$31");
+ }
return res;
}
@@ -1142,14 +1436,25 @@ static inline long strnlen_user(const char __user *s, long n)
long res;
might_fault();
- __asm__ __volatile__(
- "move\t$4, %1\n\t"
- "move\t$5, %2\n\t"
- __MODULE_JAL(__strnlen_user_asm)
- "move\t%0, $2"
- : "=r" (res)
- : "r" (s), "r" (n)
- : "$2", "$4", "$5", __UA_t0, "$31");
+ if (segment_eq(get_fs(), get_ds())) {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ __MODULE_JAL(__strnlen_kernel_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s), "r" (n)
+ : "$2", "$4", "$5", __UA_t0, "$31");
+ } else {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, %2\n\t"
+ __MODULE_JAL(__strnlen_user_asm)
+ "move\t%0, $2"
+ : "=r" (res)
+ : "r" (s), "r" (n)
+ : "$2", "$4", "$5", __UA_t0, "$31");
+ }
return res;
}
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index c33a9564fb4..708c5d41490 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -55,6 +55,9 @@ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
#define Ip_u2u1u3(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+#define Ip_u3u2u1(op) \
+void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+
#define Ip_u3u1u2(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
@@ -64,6 +67,9 @@ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
#define Ip_u2s3u1(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c)
+#define Ip_s3s1s2(op) \
+void ISAOPC(op)(u32 **buf, int a, int b, int c)
+
#define Ip_u2u1s3(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
@@ -74,6 +80,9 @@ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \
#define Ip_u1u2(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
+#define Ip_u2u1(op) \
+void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
+
#define Ip_u1s2(op) \
void ISAOPC(op)(u32 **buf, unsigned int a, signed int b)
@@ -99,6 +108,7 @@ Ip_u2u1s3(_daddiu);
Ip_u3u1u2(_daddu);
Ip_u2u1msbu3(_dins);
Ip_u2u1msbu3(_dinsm);
+Ip_u1u2(_divu);
Ip_u1u2u3(_dmfc0);
Ip_u1u2u3(_dmtc0);
Ip_u2u1u3(_drotr);
@@ -114,16 +124,22 @@ Ip_u2u1msbu3(_ext);
Ip_u2u1msbu3(_ins);
Ip_u1(_j);
Ip_u1(_jal);
+Ip_u2u1(_jalr);
Ip_u1(_jr);
+Ip_u2s3u1(_lb);
Ip_u2s3u1(_ld);
Ip_u3u1u2(_ldx);
+Ip_u2s3u1(_lh);
Ip_u2s3u1(_ll);
Ip_u2s3u1(_lld);
Ip_u1s2(_lui);
Ip_u2s3u1(_lw);
Ip_u3u1u2(_lwx);
Ip_u1u2u3(_mfc0);
+Ip_u1(_mfhi);
+Ip_u1(_mflo);
Ip_u1u2u3(_mtc0);
+Ip_u3u1u2(_mul);
Ip_u3u1u2(_or);
Ip_u2u1u3(_ori);
Ip_u2s3u1(_pref);
@@ -133,17 +149,26 @@ Ip_u2s3u1(_sc);
Ip_u2s3u1(_scd);
Ip_u2s3u1(_sd);
Ip_u2u1u3(_sll);
+Ip_u3u2u1(_sllv);
+Ip_s3s1s2(_slt);
+Ip_u2u1s3(_sltiu);
+Ip_u3u1u2(_sltu);
Ip_u2u1u3(_sra);
Ip_u2u1u3(_srl);
+Ip_u3u2u1(_srlv);
Ip_u3u1u2(_subu);
Ip_u2s3u1(_sw);
+Ip_u1(_sync);
Ip_u1(_syscall);
Ip_0(_tlbp);
Ip_0(_tlbr);
Ip_0(_tlbwi);
Ip_0(_tlbwr);
+Ip_u1(_wait);
+Ip_u2u1(_wsbh);
Ip_u3u1u2(_xor);
Ip_u2u1u3(_xori);
+Ip_u2u1(_yield);
/* Handle labels. */
@@ -264,6 +289,8 @@ void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
+void uasm_il_beq(u32 **p, struct uasm_reloc **r, unsigned int r1,
+ unsigned int r2, int lid);
void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 63c9c886173..e55813029d5 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -14,16 +14,21 @@
#include <uapi/asm/unistd.h>
+#ifdef CONFIG_MIPS32_N32
+#define NR_syscalls (__NR_N32_Linux + __NR_N32_Linux_syscalls)
+#elif defined(CONFIG_64BIT)
+#define NR_syscalls (__NR_64_Linux + __NR_64_Linux_syscalls)
+#else
+#define NR_syscalls (__NR_O32_Linux + __NR_O32_Linux_syscalls)
+#endif
#ifndef __ASSEMBLY__
-#define __ARCH_OMIT_COMPAT_SYS_GETDENTS64
#define __ARCH_WANT_OLD_READDIR
#define __ARCH_WANT_SYS_ALARM
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_IPC
#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
diff --git a/arch/mips/include/asm/vga.h b/arch/mips/include/asm/vga.h
index f4cff7e4fa8..f82c83749a0 100644
--- a/arch/mips/include/asm/vga.h
+++ b/arch/mips/include/asm/vga.h
@@ -6,6 +6,7 @@
#ifndef _ASM_VGA_H
#define _ASM_VGA_H
+#include <asm/addrspace.h>
#include <asm/byteorder.h>
/*
@@ -13,7 +14,7 @@
* access the videoram directly without any black magic.
*/
-#define VGA_MAP_MEM(x, s) (0xb0000000L + (unsigned long)(x))
+#define VGA_MAP_MEM(x, s) CKSEG1ADDR(0x10000000L + (unsigned long)(x))
#define vga_readb(x) (*(x))
#define vga_writeb(x, y) (*(y) = (x))
diff --git a/arch/mips/include/asm/vpe.h b/arch/mips/include/asm/vpe.h
index c6e1b961537..7849f3978fe 100644
--- a/arch/mips/include/asm/vpe.h
+++ b/arch/mips/include/asm/vpe.h
@@ -1,24 +1,95 @@
/*
- * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
+ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*/
-
#ifndef _ASM_VPE_H
#define _ASM_VPE_H
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+
+#define VPE_MODULE_NAME "vpe"
+#define VPE_MODULE_MINOR 1
+
+/* grab the likely amount of memory we will need. */
+#ifdef CONFIG_MIPS_VPE_LOADER_TOM
+#define P_SIZE (2 * 1024 * 1024)
+#else
+/* add an overhead to the max kmalloc size for non-striped symbols/etc */
+#define P_SIZE (256 * 1024)
+#endif
+
+#define MAX_VPES 16
+#define VPE_PATH_MAX 256
+
+static inline int aprp_cpu_index(void)
+{
+#ifdef CONFIG_MIPS_CMP
+ return setup_max_cpus;
+#else
+ extern int tclimit;
+ return tclimit;
+#endif
+}
+
+enum vpe_state {
+ VPE_STATE_UNUSED = 0,
+ VPE_STATE_INUSE,
+ VPE_STATE_RUNNING
+};
+
+enum tc_state {
+ TC_STATE_UNUSED = 0,
+ TC_STATE_INUSE,
+ TC_STATE_RUNNING,
+ TC_STATE_DYNAMIC
+};
+
+struct vpe {
+ enum vpe_state state;
+
+ /* (device) minor associated with this vpe */
+ int minor;
+
+ /* elfloader stuff */
+ void *load_addr;
+ unsigned long len;
+ char *pbuffer;
+ unsigned long plen;
+ char cwd[VPE_PATH_MAX];
+
+ unsigned long __start;
+
+ /* tc's associated with this vpe */
+ struct list_head tc;
+
+ /* The list of vpe's */
+ struct list_head list;
+
+ /* shared symbol address */
+ void *shared_ptr;
+
+ /* the list of who wants to know when something major happens */
+ struct list_head notify;
+
+ unsigned int ntcs;
+};
+
+struct tc {
+ enum tc_state state;
+ int index;
+
+ struct vpe *pvpe; /* parent VPE */
+ struct list_head tc; /* The list of TC's with this VPE */
+ struct list_head list; /* The global list of tc's */
+};
+
struct vpe_notifications {
void (*start)(int vpe);
void (*stop)(int vpe);
@@ -26,12 +97,34 @@ struct vpe_notifications {
struct list_head list;
};
+struct vpe_control {
+ spinlock_t vpe_list_lock;
+ struct list_head vpe_list; /* Virtual processing elements */
+ spinlock_t tc_list_lock;
+ struct list_head tc_list; /* Thread contexts */
+};
+
+extern unsigned long physical_memsize;
+extern struct vpe_control vpecontrol;
+extern const struct file_operations vpe_fops;
+
+int vpe_notify(int index, struct vpe_notifications *notify);
+
+void *vpe_get_shared(int index);
+char *vpe_getcwd(int index);
+
+struct vpe *get_vpe(int minor);
+struct tc *get_tc(int index);
+struct vpe *alloc_vpe(int minor);
+struct tc *alloc_tc(int index);
+void release_vpe(struct vpe *v);
-extern int vpe_notify(int index, struct vpe_notifications *notify);
+void *alloc_progmem(unsigned long len);
+void release_progmem(void *ptr);
-extern void *vpe_get_shared(int index);
-extern int vpe_getuid(int index);
-extern int vpe_getgid(int index);
-extern char *vpe_getcwd(int index);
+int __weak vpe_run(struct vpe *v);
+void cleanup_tc(struct tc *tc);
+int __init vpe_module_init(void);
+void __exit vpe_module_exit(void);
#endif /* _ASM_VPE_H */
diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild
index be7196eacb8..96fe7395ed8 100644
--- a/arch/mips/include/uapi/asm/Kbuild
+++ b/arch/mips/include/uapi/asm/Kbuild
@@ -4,6 +4,7 @@ include include/uapi/asm-generic/Kbuild.asm
generic-y += auxvec.h
generic-y += ipcbuf.h
+header-y += bitfield.h
header-y += bitsperlong.h
header-y += break.h
header-y += byteorder.h
diff --git a/arch/mips/include/uapi/asm/bitfield.h b/arch/mips/include/uapi/asm/bitfield.h
new file mode 100644
index 00000000000..ad9861359ce
--- /dev/null
+++ b/arch/mips/include/uapi/asm/bitfield.h
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __UAPI_ASM_BITFIELD_H
+#define __UAPI_ASM_BITFIELD_H
+
+/*
+ * * Damn ... bitfields depend from byteorder :-(
+ * */
+#ifdef __MIPSEB__
+#define __BITFIELD_FIELD(field, more) \
+ field; \
+ more
+
+#elif defined(__MIPSEL__)
+
+#define __BITFIELD_FIELD(field, more) \
+ more \
+ field;
+
+#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */
+#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
+#endif
+
+#endif /* __UAPI_ASM_BITFIELD_H */
diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
index 31575e2fd1b..02d645d7aa9 100644
--- a/arch/mips/include/uapi/asm/errno.h
+++ b/arch/mips/include/uapi/asm/errno.h
@@ -102,7 +102,7 @@
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define EALREADY 149 /* Operation already in progress */
#define EINPROGRESS 150 /* Operation now in progress */
-#define ESTALE 151 /* Stale NFS file handle */
+#define ESTALE 151 /* Stale file handle */
#define ECANCELED 158 /* AIO operation canceled */
/*
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
index e5a676e3d3c..4bfdb9d4c18 100644
--- a/arch/mips/include/uapi/asm/inst.h
+++ b/arch/mips/include/uapi/asm/inst.h
@@ -8,10 +8,13 @@
* Copyright (C) 1996, 2000 by Ralf Baechle
* Copyright (C) 2006 by Thiemo Seufer
* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2014 Imagination Technologies Ltd.
*/
#ifndef _UAPI_ASM_INST_H
#define _UAPI_ASM_INST_H
+#include <asm/bitfield.h>
+
/*
* Major opcodes; before MIPS IV cop1x was called cop3.
*/
@@ -73,10 +76,17 @@ enum spec2_op {
enum spec3_op {
ext_op, dextm_op, dextu_op, dext_op,
ins_op, dinsm_op, dinsu_op, dins_op,
- lx_op = 0x0a,
- bshfl_op = 0x20,
- dbshfl_op = 0x24,
- rdhwr_op = 0x3b
+ yield_op = 0x09, lx_op = 0x0a,
+ lwle_op = 0x19, lwre_op = 0x1a,
+ cachee_op = 0x1b, sbe_op = 0x1c,
+ she_op = 0x1d, sce_op = 0x1e,
+ swe_op = 0x1f, bshfl_op = 0x20,
+ swle_op = 0x21, swre_op = 0x22,
+ prefe_op = 0x23, dbshfl_op = 0x24,
+ lbue_op = 0x28, lhue_op = 0x29,
+ lbe_op = 0x2c, lhe_op = 0x2d,
+ lle_op = 0x2e, lwe_op = 0x2f,
+ rdhwr_op = 0x3b
};
/*
@@ -98,8 +108,9 @@ enum rt_op {
*/
enum cop_op {
mfc_op = 0x00, dmfc_op = 0x01,
- cfc_op = 0x02, mtc_op = 0x04,
- dmtc_op = 0x05, ctc_op = 0x06,
+ cfc_op = 0x02, mfhc_op = 0x03,
+ mtc_op = 0x04, dmtc_op = 0x05,
+ ctc_op = 0x06, mthc_op = 0x07,
bc_op = 0x08, cop_op = 0x10,
copm_op = 0x18
};
@@ -117,7 +128,8 @@ enum bcop_op {
enum cop0_coi_func {
tlbr_op = 0x01, tlbwi_op = 0x02,
tlbwr_op = 0x06, tlbp_op = 0x08,
- rfe_op = 0x10, eret_op = 0x18
+ rfe_op = 0x10, eret_op = 0x18,
+ wait_op = 0x20,
};
/*
@@ -162,8 +174,8 @@ enum cop1_sdw_func {
*/
enum cop1x_func {
lwxc1_op = 0x00, ldxc1_op = 0x01,
- pfetch_op = 0x07, swxc1_op = 0x08,
- sdxc1_op = 0x09, madd_s_op = 0x20,
+ swxc1_op = 0x08, sdxc1_op = 0x09,
+ pfetch_op = 0x0f, madd_s_op = 0x20,
madd_d_op = 0x21, madd_e_op = 0x22,
msub_s_op = 0x28, msub_d_op = 0x29,
msub_e_op = 0x2a, nmadd_s_op = 0x30,
@@ -194,6 +206,16 @@ enum lx_func {
};
/*
+ * BSHFL opcodes
+ */
+enum bshfl_func {
+ wsbh_op = 0x2,
+ dshd_op = 0x5,
+ seb_op = 0x10,
+ seh_op = 0x18,
+};
+
+/*
* (microMIPS) Major opcodes.
*/
enum mm_major_op {
@@ -236,17 +258,23 @@ enum mm_32i_minor_op {
enum mm_32a_minor_op {
mm_sll32_op = 0x000,
mm_ins_op = 0x00c,
+ mm_sllv32_op = 0x010,
mm_ext_op = 0x02c,
mm_pool32axf_op = 0x03c,
mm_srl32_op = 0x040,
mm_sra_op = 0x080,
+ mm_srlv32_op = 0x090,
mm_rotr_op = 0x0c0,
mm_lwxs_op = 0x118,
mm_addu32_op = 0x150,
mm_subu32_op = 0x1d0,
+ mm_wsbh_op = 0x1ec,
+ mm_mul_op = 0x210,
mm_and_op = 0x250,
mm_or32_op = 0x290,
mm_xor32_op = 0x310,
+ mm_slt_op = 0x350,
+ mm_sltu_op = 0x390,
};
/*
@@ -286,15 +314,20 @@ enum mm_32axf_minor_op {
mm_mfc0_op = 0x003,
mm_mtc0_op = 0x00b,
mm_tlbp_op = 0x00d,
+ mm_mfhi32_op = 0x035,
mm_jalr_op = 0x03c,
mm_tlbr_op = 0x04d,
+ mm_mflo32_op = 0x075,
mm_jalrhb_op = 0x07c,
mm_tlbwi_op = 0x08d,
mm_tlbwr_op = 0x0cd,
mm_jalrs_op = 0x13c,
mm_jalrshb_op = 0x17c,
+ mm_sync_op = 0x1ad,
mm_syscall_op = 0x22d,
+ mm_wait_op = 0x24d,
mm_eret_op = 0x3cd,
+ mm_divu_op = 0x5dc,
};
/*
@@ -397,8 +430,10 @@ enum mm_32f_73_minor_op {
mm_movt1_op = 0xa5,
mm_ftruncw_op = 0xac,
mm_fneg1_op = 0xad,
+ mm_mfhc1_op = 0xc0,
mm_froundl_op = 0xcc,
mm_fcvtd1_op = 0xcd,
+ mm_mthc1_op = 0xe0,
mm_froundw_op = 0xec,
mm_fcvts1_op = 0xed,
};
@@ -470,125 +505,116 @@ enum MIPS6e_i8_func {
*/
#define MM_NOP16 0x0c00
-/*
- * Damn ... bitfields depend from byteorder :-(
- */
-#ifdef __MIPSEB__
-#define BITFIELD_FIELD(field, more) \
- field; \
- more
-
-#elif defined(__MIPSEL__)
-
-#define BITFIELD_FIELD(field, more) \
- more \
- field;
-
-#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */
-#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
-#endif
-
struct j_format {
- BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */
- BITFIELD_FIELD(unsigned int target : 26,
+ __BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */
+ __BITFIELD_FIELD(unsigned int target : 26,
;))
};
struct i_format { /* signed immediate format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rs : 5,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(signed int simmediate : 16,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(signed int simmediate : 16,
;))))
};
struct u_format { /* unsigned immediate format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rs : 5,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int uimmediate : 16,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int uimmediate : 16,
;))))
};
struct c_format { /* Cache (>= R6000) format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rs : 5,
- BITFIELD_FIELD(unsigned int c_op : 3,
- BITFIELD_FIELD(unsigned int cache : 2,
- BITFIELD_FIELD(unsigned int simmediate : 16,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(unsigned int c_op : 3,
+ __BITFIELD_FIELD(unsigned int cache : 2,
+ __BITFIELD_FIELD(unsigned int simmediate : 16,
;)))))
};
struct r_format { /* Register format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rs : 5,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int rd : 5,
- BITFIELD_FIELD(unsigned int re : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int rd : 5,
+ __BITFIELD_FIELD(unsigned int re : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct p_format { /* Performance counter format (R10000) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rs : 5,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int rd : 5,
- BITFIELD_FIELD(unsigned int re : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int rd : 5,
+ __BITFIELD_FIELD(unsigned int re : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct f_format { /* FPU register format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int : 1,
- BITFIELD_FIELD(unsigned int fmt : 4,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int rd : 5,
- BITFIELD_FIELD(unsigned int re : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int : 1,
+ __BITFIELD_FIELD(unsigned int fmt : 4,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int rd : 5,
+ __BITFIELD_FIELD(unsigned int re : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;)))))))
};
struct ma_format { /* FPU multiply and add format (MIPS IV) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int fr : 5,
- BITFIELD_FIELD(unsigned int ft : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int func : 4,
- BITFIELD_FIELD(unsigned int fmt : 2,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int fr : 5,
+ __BITFIELD_FIELD(unsigned int ft : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int func : 4,
+ __BITFIELD_FIELD(unsigned int fmt : 2,
;)))))))
};
struct b_format { /* BREAK and SYSCALL */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int code : 20,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int code : 20,
+ __BITFIELD_FIELD(unsigned int func : 6,
;)))
};
struct ps_format { /* MIPS-3D / paired single format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rs : 5,
- BITFIELD_FIELD(unsigned int ft : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(unsigned int ft : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct v_format { /* MDMX vector format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int sel : 4,
- BITFIELD_FIELD(unsigned int fmt : 1,
- BITFIELD_FIELD(unsigned int vt : 5,
- BITFIELD_FIELD(unsigned int vs : 5,
- BITFIELD_FIELD(unsigned int vd : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int sel : 4,
+ __BITFIELD_FIELD(unsigned int fmt : 1,
+ __BITFIELD_FIELD(unsigned int vt : 5,
+ __BITFIELD_FIELD(unsigned int vs : 5,
+ __BITFIELD_FIELD(unsigned int vd : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;)))))))
};
+struct spec3_format { /* SPEC3 */
+ __BITFIELD_FIELD(unsigned int opcode:6,
+ __BITFIELD_FIELD(unsigned int rs:5,
+ __BITFIELD_FIELD(unsigned int rt:5,
+ __BITFIELD_FIELD(signed int simmediate:9,
+ __BITFIELD_FIELD(unsigned int func:7,
+ ;)))))
+};
+
/*
* microMIPS instruction formats (32-bit length)
*
@@ -597,141 +623,141 @@ struct v_format { /* MDMX vector format */
* if it is MIPS32 instruction re-encoded for use in the microMIPS ASE.
*/
struct fb_format { /* FPU branch format (MIPS32) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int bc : 5,
- BITFIELD_FIELD(unsigned int cc : 3,
- BITFIELD_FIELD(unsigned int flag : 2,
- BITFIELD_FIELD(signed int simmediate : 16,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int bc : 5,
+ __BITFIELD_FIELD(unsigned int cc : 3,
+ __BITFIELD_FIELD(unsigned int flag : 2,
+ __BITFIELD_FIELD(signed int simmediate : 16,
;)))))
};
struct fp0_format { /* FPU multiply and add format (MIPS32) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int fmt : 5,
- BITFIELD_FIELD(unsigned int ft : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int fmt : 5,
+ __BITFIELD_FIELD(unsigned int ft : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct mm_fp0_format { /* FPU multipy and add format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int ft : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int fmt : 3,
- BITFIELD_FIELD(unsigned int op : 2,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int ft : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int fmt : 3,
+ __BITFIELD_FIELD(unsigned int op : 2,
+ __BITFIELD_FIELD(unsigned int func : 6,
;)))))))
};
struct fp1_format { /* FPU mfc1 and cfc1 format (MIPS32) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int op : 5,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int op : 5,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct mm_fp1_format { /* FPU mfc1 and cfc1 format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fmt : 2,
- BITFIELD_FIELD(unsigned int op : 8,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fmt : 2,
+ __BITFIELD_FIELD(unsigned int op : 8,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct mm_fp2_format { /* FPU movt and movf format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int cc : 3,
- BITFIELD_FIELD(unsigned int zero : 2,
- BITFIELD_FIELD(unsigned int fmt : 2,
- BITFIELD_FIELD(unsigned int op : 3,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int cc : 3,
+ __BITFIELD_FIELD(unsigned int zero : 2,
+ __BITFIELD_FIELD(unsigned int fmt : 2,
+ __BITFIELD_FIELD(unsigned int op : 3,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))))
};
struct mm_fp3_format { /* FPU abs and neg format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fmt : 3,
- BITFIELD_FIELD(unsigned int op : 7,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fmt : 3,
+ __BITFIELD_FIELD(unsigned int op : 7,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct mm_fp4_format { /* FPU c.cond format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int cc : 3,
- BITFIELD_FIELD(unsigned int fmt : 3,
- BITFIELD_FIELD(unsigned int cond : 4,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int cc : 3,
+ __BITFIELD_FIELD(unsigned int fmt : 3,
+ __BITFIELD_FIELD(unsigned int cond : 4,
+ __BITFIELD_FIELD(unsigned int func : 6,
;)))))))
};
struct mm_fp5_format { /* FPU lwxc1 and swxc1 format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int index : 5,
- BITFIELD_FIELD(unsigned int base : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int op : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int index : 5,
+ __BITFIELD_FIELD(unsigned int base : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int op : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct fp6_format { /* FPU madd and msub format (MIPS IV) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int fr : 5,
- BITFIELD_FIELD(unsigned int ft : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int fr : 5,
+ __BITFIELD_FIELD(unsigned int ft : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct mm_fp6_format { /* FPU madd and msub format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int ft : 5,
- BITFIELD_FIELD(unsigned int fs : 5,
- BITFIELD_FIELD(unsigned int fd : 5,
- BITFIELD_FIELD(unsigned int fr : 5,
- BITFIELD_FIELD(unsigned int func : 6,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int ft : 5,
+ __BITFIELD_FIELD(unsigned int fs : 5,
+ __BITFIELD_FIELD(unsigned int fd : 5,
+ __BITFIELD_FIELD(unsigned int fr : 5,
+ __BITFIELD_FIELD(unsigned int func : 6,
;))))))
};
struct mm_i_format { /* Immediate format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(unsigned int rs : 5,
- BITFIELD_FIELD(signed int simmediate : 16,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(signed int simmediate : 16,
;))))
};
struct mm_m_format { /* Multi-word load/store format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rd : 5,
- BITFIELD_FIELD(unsigned int base : 5,
- BITFIELD_FIELD(unsigned int func : 4,
- BITFIELD_FIELD(signed int simmediate : 12,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rd : 5,
+ __BITFIELD_FIELD(unsigned int base : 5,
+ __BITFIELD_FIELD(unsigned int func : 4,
+ __BITFIELD_FIELD(signed int simmediate : 12,
;)))))
};
struct mm_x_format { /* Scaled indexed load format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int index : 5,
- BITFIELD_FIELD(unsigned int base : 5,
- BITFIELD_FIELD(unsigned int rd : 5,
- BITFIELD_FIELD(unsigned int func : 11,
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int index : 5,
+ __BITFIELD_FIELD(unsigned int base : 5,
+ __BITFIELD_FIELD(unsigned int rd : 5,
+ __BITFIELD_FIELD(unsigned int func : 11,
;)))))
};
@@ -739,51 +765,51 @@ struct mm_x_format { /* Scaled indexed load format (microMIPS) */
* microMIPS instruction formats (16-bit length)
*/
struct mm_b0_format { /* Unconditional branch format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(signed int simmediate : 10,
- BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(signed int simmediate : 10,
+ __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
;)))
};
struct mm_b1_format { /* Conditional branch format (microMIPS) */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rs : 3,
- BITFIELD_FIELD(signed int simmediate : 7,
- BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rs : 3,
+ __BITFIELD_FIELD(signed int simmediate : 7,
+ __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
;))))
};
struct mm16_m_format { /* Multi-word load/store format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int func : 4,
- BITFIELD_FIELD(unsigned int rlist : 2,
- BITFIELD_FIELD(unsigned int imm : 4,
- BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int func : 4,
+ __BITFIELD_FIELD(unsigned int rlist : 2,
+ __BITFIELD_FIELD(unsigned int imm : 4,
+ __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
;)))))
};
struct mm16_rb_format { /* Signed immediate format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rt : 3,
- BITFIELD_FIELD(unsigned int base : 3,
- BITFIELD_FIELD(signed int simmediate : 4,
- BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rt : 3,
+ __BITFIELD_FIELD(unsigned int base : 3,
+ __BITFIELD_FIELD(signed int simmediate : 4,
+ __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
;)))))
};
struct mm16_r3_format { /* Load from global pointer format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rt : 3,
- BITFIELD_FIELD(signed int simmediate : 7,
- BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rt : 3,
+ __BITFIELD_FIELD(signed int simmediate : 7,
+ __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
;))))
};
struct mm16_r5_format { /* Load/store from stack pointer format */
- BITFIELD_FIELD(unsigned int opcode : 6,
- BITFIELD_FIELD(unsigned int rt : 5,
- BITFIELD_FIELD(signed int simmediate : 5,
- BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(unsigned int rt : 5,
+ __BITFIELD_FIELD(signed int simmediate : 5,
+ __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
;))))
};
@@ -791,57 +817,57 @@ struct mm16_r5_format { /* Load/store from stack pointer format */
* MIPS16e instruction formats (16-bit length)
*/
struct m16e_rr {
- BITFIELD_FIELD(unsigned int opcode : 5,
- BITFIELD_FIELD(unsigned int rx : 3,
- BITFIELD_FIELD(unsigned int nd : 1,
- BITFIELD_FIELD(unsigned int l : 1,
- BITFIELD_FIELD(unsigned int ra : 1,
- BITFIELD_FIELD(unsigned int func : 5,
+ __BITFIELD_FIELD(unsigned int opcode : 5,
+ __BITFIELD_FIELD(unsigned int rx : 3,
+ __BITFIELD_FIELD(unsigned int nd : 1,
+ __BITFIELD_FIELD(unsigned int l : 1,
+ __BITFIELD_FIELD(unsigned int ra : 1,
+ __BITFIELD_FIELD(unsigned int func : 5,
;))))))
};
struct m16e_jal {
- BITFIELD_FIELD(unsigned int opcode : 5,
- BITFIELD_FIELD(unsigned int x : 1,
- BITFIELD_FIELD(unsigned int imm20_16 : 5,
- BITFIELD_FIELD(signed int imm25_21 : 5,
+ __BITFIELD_FIELD(unsigned int opcode : 5,
+ __BITFIELD_FIELD(unsigned int x : 1,
+ __BITFIELD_FIELD(unsigned int imm20_16 : 5,
+ __BITFIELD_FIELD(signed int imm25_21 : 5,
;))))
};
struct m16e_i64 {
- BITFIELD_FIELD(unsigned int opcode : 5,
- BITFIELD_FIELD(unsigned int func : 3,
- BITFIELD_FIELD(unsigned int imm : 8,
+ __BITFIELD_FIELD(unsigned int opcode : 5,
+ __BITFIELD_FIELD(unsigned int func : 3,
+ __BITFIELD_FIELD(unsigned int imm : 8,
;)))
};
struct m16e_ri64 {
- BITFIELD_FIELD(unsigned int opcode : 5,
- BITFIELD_FIELD(unsigned int func : 3,
- BITFIELD_FIELD(unsigned int ry : 3,
- BITFIELD_FIELD(unsigned int imm : 5,
+ __BITFIELD_FIELD(unsigned int opcode : 5,
+ __BITFIELD_FIELD(unsigned int func : 3,
+ __BITFIELD_FIELD(unsigned int ry : 3,
+ __BITFIELD_FIELD(unsigned int imm : 5,
;))))
};
struct m16e_ri {
- BITFIELD_FIELD(unsigned int opcode : 5,
- BITFIELD_FIELD(unsigned int rx : 3,
- BITFIELD_FIELD(unsigned int imm : 8,
+ __BITFIELD_FIELD(unsigned int opcode : 5,
+ __BITFIELD_FIELD(unsigned int rx : 3,
+ __BITFIELD_FIELD(unsigned int imm : 8,
;)))
};
struct m16e_rri {
- BITFIELD_FIELD(unsigned int opcode : 5,
- BITFIELD_FIELD(unsigned int rx : 3,
- BITFIELD_FIELD(unsigned int ry : 3,
- BITFIELD_FIELD(unsigned int imm : 5,
+ __BITFIELD_FIELD(unsigned int opcode : 5,
+ __BITFIELD_FIELD(unsigned int rx : 3,
+ __BITFIELD_FIELD(unsigned int ry : 3,
+ __BITFIELD_FIELD(unsigned int imm : 5,
;))))
};
struct m16e_i8 {
- BITFIELD_FIELD(unsigned int opcode : 5,
- BITFIELD_FIELD(unsigned int func : 3,
- BITFIELD_FIELD(unsigned int imm : 8,
+ __BITFIELD_FIELD(unsigned int opcode : 5,
+ __BITFIELD_FIELD(unsigned int func : 3,
+ __BITFIELD_FIELD(unsigned int imm : 8,
;)))
};
@@ -860,6 +886,7 @@ union mips_instruction {
struct b_format b_format;
struct ps_format ps_format;
struct v_format v_format;
+ struct spec3_format spec3_format;
struct fb_format fb_format;
struct fp0_format fp0_format;
struct mm_fp0_format mm_fp0_format;
diff --git a/arch/mips/include/uapi/asm/kvm.h b/arch/mips/include/uapi/asm/kvm.h
index f09ff5ae205..2c04b6d9ff8 100644
--- a/arch/mips/include/uapi/asm/kvm.h
+++ b/arch/mips/include/uapi/asm/kvm.h
@@ -106,6 +106,41 @@ struct kvm_fpu {
#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33)
#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34)
+/* KVM specific control registers */
+
+/*
+ * CP0_Count control
+ * DC: Set 0: Master disable CP0_Count and set COUNT_RESUME to now
+ * Set 1: Master re-enable CP0_Count with unchanged bias, handling timer
+ * interrupts since COUNT_RESUME
+ * This can be used to freeze the timer to get a consistent snapshot of
+ * the CP0_Count and timer interrupt pending state, while also resuming
+ * safely without losing time or guest timer interrupts.
+ * Other: Reserved, do not change.
+ */
+#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
+ 0x20000 | 0)
+#define KVM_REG_MIPS_COUNT_CTL_DC 0x00000001
+
+/*
+ * CP0_Count resume monotonic nanoseconds
+ * The monotonic nanosecond time of the last set of COUNT_CTL.DC (master
+ * disable). Any reads and writes of Count related registers while
+ * COUNT_CTL.DC=1 will appear to occur at this time. When COUNT_CTL.DC is
+ * cleared again (master enable) any timer interrupts since this time will be
+ * emulated.
+ * Modifications to times in the future are rejected.
+ */
+#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
+ 0x20000 | 1)
+/*
+ * CP0_Count rate in Hz
+ * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without
+ * discontinuities in CP0_Count.
+ */
+#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \
+ 0x20000 | 2)
+
/*
* KVM MIPS specific structures and definitions
*
diff --git a/arch/mips/include/uapi/asm/kvm_para.h b/arch/mips/include/uapi/asm/kvm_para.h
index 14fab8f0b95..7e16d7c42e6 100644
--- a/arch/mips/include/uapi/asm/kvm_para.h
+++ b/arch/mips/include/uapi/asm/kvm_para.h
@@ -1 +1,5 @@
-#include <asm-generic/kvm_para.h>
+#ifndef _UAPI_ASM_MIPS_KVM_PARA_H
+#define _UAPI_ASM_MIPS_KVM_PARA_H
+
+
+#endif /* _UAPI_ASM_MIPS_KVM_PARA_H */
diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h
index 88e292b7719..e81174432ba 100644
--- a/arch/mips/include/uapi/asm/siginfo.h
+++ b/arch/mips/include/uapi/asm/siginfo.h
@@ -33,6 +33,8 @@ struct siginfo;
#error _MIPS_SZLONG neither 32 nor 64
#endif
+#define __ARCH_SIGSYS
+
#include <asm-generic/siginfo.h>
typedef struct siginfo {
@@ -97,6 +99,13 @@ typedef struct siginfo {
__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
+
+ /* SIGSYS */
+ struct {
+ void __user *_call_addr; /* calling user insn */
+ int _syscall; /* triggering system call number */
+ unsigned int _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
} _sifields;
} siginfo_t;
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 61c01f054d1..a14baa218c7 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -94,4 +94,8 @@
#define SO_BUSY_POLL 46
+#define SO_MAX_PACING_RATE 47
+
+#define SO_BPF_EXTENSIONS 48
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/types.h b/arch/mips/include/uapi/asm/types.h
index 7ac9d0baad8..f3dd9ff0cc0 100644
--- a/arch/mips/include/uapi/asm/types.h
+++ b/arch/mips/include/uapi/asm/types.h
@@ -14,9 +14,12 @@
/*
* We don't use int-l64.h for the kernel anymore but still use it for
* userspace to avoid code changes.
+ *
+ * However, some user programs (e.g. perf) may not want this. They can
+ * flag __SANE_USERSPACE_TYPES__ to get int-ll64.h here.
*/
#ifndef __KERNEL__
-# if _MIPS_SZLONG == 64
+# if _MIPS_SZLONG == 64 && !defined(__SANE_USERSPACE_TYPES__)
# include <asm-generic/int-l64.h>
# else
# include <asm-generic/int-ll64.h>
diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h
index 1dee279f966..5805414777e 100644
--- a/arch/mips/include/uapi/asm/unistd.h
+++ b/arch/mips/include/uapi/asm/unistd.h
@@ -369,16 +369,19 @@
#define __NR_process_vm_writev (__NR_Linux + 346)
#define __NR_kcmp (__NR_Linux + 347)
#define __NR_finit_module (__NR_Linux + 348)
+#define __NR_sched_setattr (__NR_Linux + 349)
+#define __NR_sched_getattr (__NR_Linux + 350)
+#define __NR_renameat2 (__NR_Linux + 351)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 348
+#define __NR_Linux_syscalls 351
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 348
+#define __NR_O32_Linux_syscalls 351
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -695,16 +698,19 @@
#define __NR_kcmp (__NR_Linux + 306)
#define __NR_finit_module (__NR_Linux + 307)
#define __NR_getdents64 (__NR_Linux + 308)
+#define __NR_sched_setattr (__NR_Linux + 309)
+#define __NR_sched_getattr (__NR_Linux + 310)
+#define __NR_renameat2 (__NR_Linux + 311)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 308
+#define __NR_Linux_syscalls 311
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 308
+#define __NR_64_Linux_syscalls 311
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -1025,15 +1031,18 @@
#define __NR_process_vm_writev (__NR_Linux + 310)
#define __NR_kcmp (__NR_Linux + 311)
#define __NR_finit_module (__NR_Linux + 312)
+#define __NR_sched_setattr (__NR_Linux + 313)
+#define __NR_sched_getattr (__NR_Linux + 314)
+#define __NR_renameat2 (__NR_Linux + 315)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 312
+#define __NR_Linux_syscalls 315
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 312
+#define __NR_N32_Linux_syscalls 315
#endif /* _UAPI_ASM_UNISTD_H */
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 8a5ec0eedeb..088e92a79ae 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -425,8 +425,18 @@ static struct platform_device qi_lb60_audio_device = {
.id = -1,
};
+static struct gpiod_lookup_table qi_lb60_audio_gpio_table = {
+ .dev_id = "qi-lb60-audio",
+ .table = {
+ GPIO_LOOKUP("Bank B", 29, "snd", 0),
+ GPIO_LOOKUP("Bank D", 4, "amp", 0),
+ { },
+ },
+};
+
static struct platform_device *jz_platform_devices[] __initdata = {
&jz4740_udc_device,
+ &jz4740_udc_xceiv_device,
&jz4740_mmc_device,
&jz4740_nand_device,
&qi_lb60_keypad,
@@ -460,6 +470,8 @@ static int __init qi_lb60_init_platform_devices(void)
jz4740_adc_device.dev.platform_data = &qi_lb60_battery_pdata;
jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata;
+ gpiod_add_lookup_table(&qi_lb60_audio_gpio_table);
+
jz4740_serial_device_register();
spi_register_board_info(qi_lb60_spi_board_info,
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index df65677f3d0..a447101cf9f 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -14,13 +14,14 @@
*/
#include <linux/device.h>
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/dma-mapping.h>
+#include <linux/usb/musb.h>
+
#include <asm/mach-jz4740/platform.h>
#include <asm/mach-jz4740/base.h>
#include <asm/mach-jz4740/irq.h>
@@ -56,29 +57,35 @@ struct platform_device jz4740_usb_ohci_device = {
.resource = jz4740_usb_ohci_resources,
};
-/* UDC (USB gadget controller) */
-static struct resource jz4740_usb_gdt_resources[] = {
- {
- .start = JZ4740_UDC_BASE_ADDR,
- .end = JZ4740_UDC_BASE_ADDR + 0x1000 - 1,
- .flags = IORESOURCE_MEM,
+/* USB Device Controller */
+struct platform_device jz4740_udc_xceiv_device = {
+ .name = "usb_phy_gen_xceiv",
+ .id = 0,
+};
+
+static struct resource jz4740_udc_resources[] = {
+ [0] = {
+ .start = JZ4740_UDC_BASE_ADDR,
+ .end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
},
- {
- .start = JZ4740_IRQ_UDC,
- .end = JZ4740_IRQ_UDC,
- .flags = IORESOURCE_IRQ,
+ [1] = {
+ .start = JZ4740_IRQ_UDC,
+ .end = JZ4740_IRQ_UDC,
+ .flags = IORESOURCE_IRQ,
+ .name = "mc",
},
};
struct platform_device jz4740_udc_device = {
- .name = "jz-udc",
- .id = -1,
- .dev = {
- .dma_mask = &jz4740_udc_device.dev.coherent_dma_mask,
+ .name = "musb-jz4740",
+ .id = -1,
+ .dev = {
+ .dma_mask = &jz4740_udc_device.dev.coherent_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
- .num_resources = ARRAY_SIZE(jz4740_usb_gdt_resources),
- .resource = jz4740_usb_gdt_resources,
+ .num_resources = ARRAY_SIZE(jz4740_udc_resources),
+ .resource = jz4740_udc_resources,
};
/* MMC/SD controller */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 423d871a946..008a2fed058 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -17,7 +17,6 @@ endif
obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
-obj-$(CONFIG_MIPS_MT_SMTC) += cevt-smtc.o
obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o
obj-$(CONFIG_CEVT_GIC) += cevt-gic.o
obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
@@ -26,22 +25,23 @@ obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
obj-$(CONFIG_CSRC_GIC) += csrc-gic.o
obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o
-obj-$(CONFIG_CSRC_POWERTV) += csrc-powertv.o
obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o
obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
+obj-$(CONFIG_DEBUG_FS) += segment.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o
+obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_CAVIUM_OCTEON) += octeon_switch.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON) += r4k_fpu.o octeon_switch.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SMP_UP) += smp-up.o
@@ -49,13 +49,18 @@ obj-$(CONFIG_CPU_BMIPS) += smp-bmips.o bmips_vec.o
obj-$(CONFIG_MIPS_MT) += mips-mt.o
obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o
-obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.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_GIC_IPI) += smp-gic.o
obj-$(CONFIG_CPU_MIPSR2) += spram.o
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
+obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o
+obj-$(CONFIG_MIPS_VPE_LOADER_MT) += vpe-mt.o
obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
+obj-$(CONFIG_MIPS_VPE_APSP_API_CMP) += rtlx-cmp.o
+obj-$(CONFIG_MIPS_VPE_APSP_API_MT) += rtlx-mt.o
obj-$(CONFIG_I8259) += i8259.o
obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
@@ -84,6 +89,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_EARLY_PRINTK_8250) += early_printk_8250.o
obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
@@ -96,6 +102,12 @@ obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+obj-$(CONFIG_MIPS_CM) += mips-cm.o
+obj-$(CONFIG_MIPS_CPC) += mips-cpc.o
+
+obj-$(CONFIG_CPU_PM) += pm.o
+obj-$(CONFIG_MIPS_CPS_PM) += pm-cps.o
+
#
# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not
# safe to unconditionnaly use the assembler -mdsp / -mdspr2 switches
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 0c2e853c3db..4bb5107511e 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -14,8 +14,10 @@
#include <linux/mm.h>
#include <linux/kbuild.h>
#include <linux/suspend.h>
+#include <asm/pm.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
+#include <asm/smp-cps.h>
#include <linux/kvm_host.h>
@@ -63,9 +65,6 @@ void output_ptreg_defines(void)
OFFSET(PT_BVADDR, pt_regs, cp0_badvaddr);
OFFSET(PT_STATUS, pt_regs, cp0_status);
OFFSET(PT_CAUSE, pt_regs, cp0_cause);
-#ifdef CONFIG_MIPS_MT_SMTC
- OFFSET(PT_TCSTATUS, pt_regs, cp0_tcstatus);
-#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_CPU_CAVIUM_OCTEON
OFFSET(PT_MPL, pt_regs, mpl);
OFFSET(PT_MTP, pt_regs, mtp);
@@ -168,6 +167,72 @@ void output_thread_fpu_defines(void)
OFFSET(THREAD_FPR30, task_struct, thread.fpu.fpr[30]);
OFFSET(THREAD_FPR31, task_struct, thread.fpu.fpr[31]);
+ /* the least significant 64 bits of each FP register */
+ OFFSET(THREAD_FPR0_LS64, task_struct,
+ thread.fpu.fpr[0].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR1_LS64, task_struct,
+ thread.fpu.fpr[1].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR2_LS64, task_struct,
+ thread.fpu.fpr[2].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR3_LS64, task_struct,
+ thread.fpu.fpr[3].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR4_LS64, task_struct,
+ thread.fpu.fpr[4].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR5_LS64, task_struct,
+ thread.fpu.fpr[5].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR6_LS64, task_struct,
+ thread.fpu.fpr[6].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR7_LS64, task_struct,
+ thread.fpu.fpr[7].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR8_LS64, task_struct,
+ thread.fpu.fpr[8].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR9_LS64, task_struct,
+ thread.fpu.fpr[9].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR10_LS64, task_struct,
+ thread.fpu.fpr[10].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR11_LS64, task_struct,
+ thread.fpu.fpr[11].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR12_LS64, task_struct,
+ thread.fpu.fpr[12].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR13_LS64, task_struct,
+ thread.fpu.fpr[13].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR14_LS64, task_struct,
+ thread.fpu.fpr[14].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR15_LS64, task_struct,
+ thread.fpu.fpr[15].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR16_LS64, task_struct,
+ thread.fpu.fpr[16].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR17_LS64, task_struct,
+ thread.fpu.fpr[17].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR18_LS64, task_struct,
+ thread.fpu.fpr[18].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR19_LS64, task_struct,
+ thread.fpu.fpr[19].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR20_LS64, task_struct,
+ thread.fpu.fpr[20].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR21_LS64, task_struct,
+ thread.fpu.fpr[21].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR22_LS64, task_struct,
+ thread.fpu.fpr[22].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR23_LS64, task_struct,
+ thread.fpu.fpr[23].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR24_LS64, task_struct,
+ thread.fpu.fpr[24].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR25_LS64, task_struct,
+ thread.fpu.fpr[25].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR26_LS64, task_struct,
+ thread.fpu.fpr[26].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR27_LS64, task_struct,
+ thread.fpu.fpr[27].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR28_LS64, task_struct,
+ thread.fpu.fpr[28].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR29_LS64, task_struct,
+ thread.fpu.fpr[29].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR30_LS64, task_struct,
+ thread.fpu.fpr[30].val64[FPR_IDX(64, 0)]);
+ OFFSET(THREAD_FPR31_LS64, task_struct,
+ thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
+
OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
BLANK();
}
@@ -334,6 +399,20 @@ void output_pbe_defines(void)
}
#endif
+#ifdef CONFIG_CPU_PM
+void output_pm_defines(void)
+{
+ COMMENT(" PM offsets. ");
+#ifdef CONFIG_EVA
+ OFFSET(SSS_SEGCTL0, mips_static_suspend_state, segctl[0]);
+ OFFSET(SSS_SEGCTL1, mips_static_suspend_state, segctl[1]);
+ OFFSET(SSS_SEGCTL2, mips_static_suspend_state, segctl[2]);
+#endif
+ OFFSET(SSS_SP, mips_static_suspend_state, sp);
+ BLANK();
+}
+#endif
+
void output_kvm_defines(void)
{
COMMENT(" KVM/MIPS Specfic offsets. ");
@@ -397,3 +476,19 @@ void output_kvm_defines(void)
OFFSET(COP0_STATUS, mips_coproc, reg[MIPS_CP0_STATUS][0]);
BLANK();
}
+
+#ifdef CONFIG_MIPS_CPS
+void output_cps_defines(void)
+{
+ COMMENT(" MIPS CPS offsets. ");
+
+ OFFSET(COREBOOTCFG_VPEMASK, core_boot_config, vpe_mask);
+ OFFSET(COREBOOTCFG_VPECONFIG, core_boot_config, vpe_config);
+ DEFINE(COREBOOTCFG_SIZE, sizeof(struct core_boot_config));
+
+ OFFSET(VPEBOOTCFG_PC, vpe_boot_config, pc);
+ OFFSET(VPEBOOTCFG_SP, vpe_boot_config, sp);
+ OFFSET(VPEBOOTCFG_GP, vpe_boot_config, gp);
+ DEFINE(VPEBOOTCFG_SIZE, sizeof(struct vpe_boot_config));
+}
+#endif
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 202e581e609..7faf5f2bee2 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -28,6 +28,18 @@ typedef double elf_fpreg_t;
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
/*
+ * In order to be sure that we don't attempt to execute an O32 binary which
+ * requires 64 bit FP (FR=1) on a system which does not support it we refuse
+ * to execute any binary which has bits specified by the following macro set
+ * in its ELF header flags.
+ */
+#ifdef CONFIG_MIPS_O32_FP64_SUPPORT
+# define __MIPS_O32_FP64_MUST_BE_ZERO 0
+#else
+# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64
+#endif
+
+/*
* This is used to ensure we don't load something for the wrong architecture.
*/
#define elf_check_arch(hdr) \
@@ -44,6 +56,8 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
if (((__h->e_flags & EF_MIPS_ABI) != 0) && \
((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \
__res = 0; \
+ if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \
+ __res = 0; \
\
__res; \
})
diff --git a/arch/mips/kernel/bmips_vec.S b/arch/mips/kernel/bmips_vec.S
index bd79c4f9bff..290c23b5167 100644
--- a/arch/mips/kernel/bmips_vec.S
+++ b/arch/mips/kernel/bmips_vec.S
@@ -8,11 +8,11 @@
* Reset/NMI/re-entry vectors for BMIPS processors
*/
-#include <linux/init.h>
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/cacheops.h>
+#include <asm/cpu.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
@@ -91,12 +91,18 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
beqz k0, bmips_smp_entry
#if defined(CONFIG_CPU_BMIPS5000)
+ mfc0 k0, CP0_PRID
+ li k1, PRID_IMP_BMIPS5000
+ andi k0, 0xff00
+ bne k0, k1, 1f
+
/* if we're not on core 0, this must be the SMP boot signal */
li k1, (3 << 25)
mfc0 k0, $22
and k0, k1
bnez k0, bmips_smp_entry
-#endif
+1:
+#endif /* CONFIG_CPU_BMIPS5000 */
#endif /* CONFIG_SMP */
/* nope, it's just a regular NMI */
@@ -116,7 +122,7 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
jr k0
RESTORE_ALL
- .set mips3
+ .set arch=r4000
eret
/***********************************************************************
@@ -139,7 +145,12 @@ bmips_smp_entry:
xori k0, 0x04
mtc0 k0, CP0_CONFIG
+ mfc0 k0, CP0_PRID
+ andi k0, 0xff00
#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
+ li k1, PRID_IMP_BMIPS43XX
+ bne k0, k1, 2f
+
/* initialize CPU1's local I-cache */
li k0, 0x80000000
li k1, 0x80010000
@@ -150,14 +161,21 @@ bmips_smp_entry:
1: cache Index_Store_Tag_I, 0(k0)
addiu k0, 16
bne k0, k1, 1b
-#elif defined(CONFIG_CPU_BMIPS5000)
+
+ b 3f
+2:
+#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
+#if defined(CONFIG_CPU_BMIPS5000)
/* set exception vector base */
+ li k1, PRID_IMP_BMIPS5000
+ bne k0, k1, 3f
+
la k0, ebase
lw k0, 0(k0)
mtc0 k0, $15, 1
BARRIER
-#endif
-
+#endif /* CONFIG_CPU_BMIPS5000 */
+3:
/* jump back to kseg0 in case we need to remap the kseg1 area */
la k0, 1f
jr k0
@@ -221,8 +239,18 @@ END(bmips_smp_int_vec)
LEAF(bmips_enable_xks01)
#if defined(CONFIG_XKS01)
-
+ mfc0 t0, CP0_PRID
+ andi t2, t0, 0xff00
#if defined(CONFIG_CPU_BMIPS4380)
+ li t1, PRID_IMP_BMIPS43XX
+ bne t2, t1, 1f
+
+ andi t0, 0xff
+ addiu t1, t0, -PRID_REV_BMIPS4380_HI
+ bgtz t1, 2f
+ addiu t0, -PRID_REV_BMIPS4380_LO
+ bltz t0, 2f
+
mfc0 t0, $22, 3
li t1, 0x1ff0
li t2, (1 << 12) | (1 << 9)
@@ -231,7 +259,13 @@ LEAF(bmips_enable_xks01)
or t0, t2
mtc0 t0, $22, 3
BARRIER
-#elif defined(CONFIG_CPU_BMIPS5000)
+ b 2f
+1:
+#endif /* CONFIG_CPU_BMIPS4380 */
+#if defined(CONFIG_CPU_BMIPS5000)
+ li t1, PRID_IMP_BMIPS5000
+ bne t2, t1, 2f
+
mfc0 t0, $22, 5
li t1, 0x01ff
li t2, (1 << 8) | (1 << 5)
@@ -240,12 +274,8 @@ LEAF(bmips_enable_xks01)
or t0, t2
mtc0 t0, $22, 5
BARRIER
-#else
-
-#error Missing XKS01 setup
-
-#endif
-
+#endif /* CONFIG_CPU_BMIPS5000 */
+2:
#endif /* defined(CONFIG_XKS01) */
jr ra
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 4d78bf445a9..7b2df224f04 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -48,6 +48,202 @@ int __isa_exception_epc(struct pt_regs *regs)
return epc;
}
+/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
+static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};
+
+int __mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
+ unsigned long *contpc)
+{
+ union mips_instruction insn = (union mips_instruction)dec_insn.insn;
+ int bc_false = 0;
+ unsigned int fcr31;
+ unsigned int bit;
+
+ if (!cpu_has_mmips)
+ return 0;
+
+ switch (insn.mm_i_format.opcode) {
+ case mm_pool32a_op:
+ if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) ==
+ mm_pool32axf_op) {
+ switch (insn.mm_i_format.simmediate >>
+ MM_POOL32A_MINOR_SHIFT) {
+ case mm_jalr_op:
+ case mm_jalrhb_op:
+ case mm_jalrs_op:
+ case mm_jalrshb_op:
+ if (insn.mm_i_format.rt != 0) /* Not mm_jr */
+ regs->regs[insn.mm_i_format.rt] =
+ regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ *contpc = regs->regs[insn.mm_i_format.rs];
+ return 1;
+ }
+ }
+ break;
+ case mm_pool32i_op:
+ switch (insn.mm_i_format.rt) {
+ case mm_bltzals_op:
+ case mm_bltzal_op:
+ regs->regs[31] = regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ /* Fall through */
+ case mm_bltz_op:
+ if ((long)regs->regs[insn.mm_i_format.rs] < 0)
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_i_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ return 1;
+ case mm_bgezals_op:
+ case mm_bgezal_op:
+ regs->regs[31] = regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ /* Fall through */
+ case mm_bgez_op:
+ if ((long)regs->regs[insn.mm_i_format.rs] >= 0)
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_i_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ return 1;
+ case mm_blez_op:
+ if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_i_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ return 1;
+ case mm_bgtz_op:
+ if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_i_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ return 1;
+ case mm_bc2f_op:
+ case mm_bc1f_op:
+ bc_false = 1;
+ /* Fall through */
+ case mm_bc2t_op:
+ case mm_bc1t_op:
+ preempt_disable();
+ if (is_fpu_owner())
+ asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+ else
+ fcr31 = current->thread.fpu.fcr31;
+ preempt_enable();
+
+ if (bc_false)
+ fcr31 = ~fcr31;
+
+ bit = (insn.mm_i_format.rs >> 2);
+ bit += (bit != 0);
+ bit += 23;
+ if (fcr31 & (1 << bit))
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_i_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc + dec_insn.next_pc_inc;
+ return 1;
+ }
+ break;
+ case mm_pool16c_op:
+ switch (insn.mm_i_format.rt) {
+ case mm_jalr16_op:
+ case mm_jalrs16_op:
+ regs->regs[31] = regs->cp0_epc +
+ dec_insn.pc_inc + dec_insn.next_pc_inc;
+ /* Fall through */
+ case mm_jr16_op:
+ *contpc = regs->regs[insn.mm_i_format.rs];
+ return 1;
+ }
+ break;
+ case mm_beqz16_op:
+ if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0)
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_b1_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc + dec_insn.next_pc_inc;
+ return 1;
+ case mm_bnez16_op:
+ if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0)
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_b1_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc + dec_insn.next_pc_inc;
+ return 1;
+ case mm_b16_op:
+ *contpc = regs->cp0_epc + dec_insn.pc_inc +
+ (insn.mm_b0_format.simmediate << 1);
+ return 1;
+ case mm_beq32_op:
+ if (regs->regs[insn.mm_i_format.rs] ==
+ regs->regs[insn.mm_i_format.rt])
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_i_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ return 1;
+ case mm_bne32_op:
+ if (regs->regs[insn.mm_i_format.rs] !=
+ regs->regs[insn.mm_i_format.rt])
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc +
+ (insn.mm_i_format.simmediate << 1);
+ else
+ *contpc = regs->cp0_epc +
+ dec_insn.pc_inc + dec_insn.next_pc_inc;
+ return 1;
+ case mm_jalx32_op:
+ regs->regs[31] = regs->cp0_epc +
+ dec_insn.pc_inc + dec_insn.next_pc_inc;
+ *contpc = regs->cp0_epc + dec_insn.pc_inc;
+ *contpc >>= 28;
+ *contpc <<= 28;
+ *contpc |= (insn.j_format.target << 2);
+ return 1;
+ case mm_jals32_op:
+ case mm_jal32_op:
+ regs->regs[31] = regs->cp0_epc +
+ dec_insn.pc_inc + dec_insn.next_pc_inc;
+ /* Fall through */
+ case mm_j32_op:
+ *contpc = regs->cp0_epc + dec_insn.pc_inc;
+ *contpc >>= 27;
+ *contpc <<= 27;
+ *contpc |= (insn.j_format.target << 1);
+ set_isa16_mode(*contpc);
+ return 1;
+ }
+ return 0;
+}
+
/*
* Compute return address and emulate branch in microMIPS mode after an
* exception only. It does not handle compact branches/jumps and cannot
@@ -317,7 +513,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
if (regs->regs[insn.i_format.rs] ==
regs->regs[insn.i_format.rt]) {
epc = epc + 4 + (insn.i_format.simmediate << 2);
- if (insn.i_format.rt == beql_op)
+ if (insn.i_format.opcode == beql_op)
ret = BRANCH_LIKELY_TAKEN;
} else
epc += 8;
@@ -329,7 +525,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
if (regs->regs[insn.i_format.rs] !=
regs->regs[insn.i_format.rt]) {
epc = epc + 4 + (insn.i_format.simmediate << 2);
- if (insn.i_format.rt == bnel_op)
+ if (insn.i_format.opcode == bnel_op)
ret = BRANCH_LIKELY_TAKEN;
} else
epc += 8;
@@ -341,7 +537,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
/* rt field assumed to be zero */
if ((long)regs->regs[insn.i_format.rs] <= 0) {
epc = epc + 4 + (insn.i_format.simmediate << 2);
- if (insn.i_format.rt == bnel_op)
+ if (insn.i_format.opcode == blezl_op)
ret = BRANCH_LIKELY_TAKEN;
} else
epc += 8;
@@ -353,7 +549,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
/* rt field assumed to be zero */
if ((long)regs->regs[insn.i_format.rs] > 0) {
epc = epc + 4 + (insn.i_format.simmediate << 2);
- if (insn.i_format.rt == bnel_op)
+ if (insn.i_format.opcode == bgtzl_op)
ret = BRANCH_LIKELY_TAKEN;
} else
epc += 8;
@@ -366,7 +562,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case cop1_op:
preempt_disable();
if (is_fpu_owner())
- asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+ asm volatile(
+ ".set push\n"
+ "\t.set mips1\n"
+ "\tcfc1\t%0,$31\n"
+ "\t.set pop" : "=r" (fcr31));
else
fcr31 = current->thread.fpu.fcr31;
preempt_enable();
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c
index 594cbbf16d6..6093716980b 100644
--- a/arch/mips/kernel/cevt-gic.c
+++ b/arch/mips/kernel/cevt-gic.c
@@ -26,7 +26,7 @@ static int gic_next_event(unsigned long delta, struct clock_event_device *evt)
cnt = gic_read_count();
cnt += (u64)delta;
- gic_write_compare(cnt);
+ gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask));
res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0;
return res;
}
@@ -73,7 +73,8 @@ int gic_clockevent_init(void)
cd = &per_cpu(gic_clockevent_device, cpu);
cd->name = "MIPS GIC";
- cd->features = CLOCK_EVT_FEAT_ONESHOT;
+ cd->features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_C3STOP;
clockevent_set_clock(cd, gic_frequency);
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 50d3f5a8d6b..bc127e22fda 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -12,17 +12,10 @@
#include <linux/smp.h>
#include <linux/irq.h>
-#include <asm/smtc_ipi.h>
#include <asm/time.h>
#include <asm/cevt-r4k.h>
#include <asm/gic.h>
-/*
- * The SMTC Kernel for the 34K, 1004K, et. al. replaces several
- * of these routines with SMTC-specific variants.
- */
-
-#ifndef CONFIG_MIPS_MT_SMTC
static int mips_next_event(unsigned long delta,
struct clock_event_device *evt)
{
@@ -36,8 +29,6 @@ static int mips_next_event(unsigned long delta,
return res;
}
-#endif /* CONFIG_MIPS_MT_SMTC */
-
void mips_set_clock_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
@@ -47,7 +38,6 @@ void mips_set_clock_mode(enum clock_event_mode mode,
DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
int cp0_timer_irq_installed;
-#ifndef CONFIG_MIPS_MT_SMTC
irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
{
const int r2 = cpu_has_mips_r2;
@@ -72,9 +62,6 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
/* Clear Count/Compare Interrupt */
write_c0_compare(read_c0_compare());
cd = &per_cpu(mips_clockevent_device, cpu);
-#ifdef CONFIG_CEVT_GIC
- if (!gic_present)
-#endif
cd->event_handler(cd);
}
@@ -82,8 +69,6 @@ out:
return IRQ_HANDLED;
}
-#endif /* Not CONFIG_MIPS_MT_SMTC */
-
struct irqaction c0_compare_irqaction = {
.handler = c0_compare_interrupt,
.flags = IRQF_PERCPU | IRQF_TIMER,
@@ -170,7 +155,6 @@ int c0_compare_int_usable(void)
return 1;
}
-#ifndef CONFIG_MIPS_MT_SMTC
int r4k_clockevent_init(void)
{
unsigned int cpu = smp_processor_id();
@@ -195,7 +179,9 @@ int r4k_clockevent_init(void)
cd = &per_cpu(mips_clockevent_device, cpu);
cd->name = "MIPS";
- cd->features = CLOCK_EVT_FEAT_ONESHOT;
+ cd->features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_C3STOP |
+ CLOCK_EVT_FEAT_PERCPU;
clockevent_set_clock(cd, mips_hpt_frequency);
@@ -210,9 +196,6 @@ int r4k_clockevent_init(void)
cd->set_mode = mips_set_clock_mode;
cd->event_handler = mips_event_handler;
-#ifdef CONFIG_CEVT_GIC
- if (!gic_present)
-#endif
clockevents_register_device(cd);
if (cp0_timer_irq_installed)
@@ -225,4 +208,3 @@ int r4k_clockevent_init(void)
return 0;
}
-#endif /* Not CONFIG_MIPS_MT_SMTC */
diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c
deleted file mode 100644
index b6cf0a60d89..00000000000
--- a/arch/mips/kernel/cevt-smtc.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2007 MIPS Technologies, Inc.
- * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
- * Copyright (C) 2008 Kevin D. Kissell, Paralogos sarl
- */
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/percpu.h>
-#include <linux/smp.h>
-#include <linux/irq.h>
-
-#include <asm/smtc_ipi.h>
-#include <asm/time.h>
-#include <asm/cevt-r4k.h>
-
-/*
- * Variant clock event timer support for SMTC on MIPS 34K, 1004K
- * or other MIPS MT cores.
- *
- * Notes on SMTC Support:
- *
- * SMTC has multiple microthread TCs pretending to be Linux CPUs.
- * But there's only one Count/Compare pair per VPE, and Compare
- * interrupts are taken opportunisitically by available TCs
- * bound to the VPE with the Count register. The new timer
- * framework provides for global broadcasts, but we really
- * want VPE-level multicasts for best behavior. So instead
- * of invoking the high-level clock-event broadcast code,
- * this version of SMTC support uses the historical SMTC
- * multicast mechanisms "under the hood", appearing to the
- * generic clock layer as if the interrupts are per-CPU.
- *
- * The approach taken here is to maintain a set of NR_CPUS
- * virtual timers, and track which "CPU" needs to be alerted
- * at each event.
- *
- * It's unlikely that we'll see a MIPS MT core with more than
- * 2 VPEs, but we *know* that we won't need to handle more
- * VPEs than we have "CPUs". So NCPUs arrays of NCPUs elements
- * is always going to be overkill, but always going to be enough.
- */
-
-unsigned long smtc_nexttime[NR_CPUS][NR_CPUS];
-static int smtc_nextinvpe[NR_CPUS];
-
-/*
- * Timestamps stored are absolute values to be programmed
- * into Count register. Valid timestamps will never be zero.
- * If a Zero Count value is actually calculated, it is converted
- * to be a 1, which will introduce 1 or two CPU cycles of error
- * roughly once every four billion events, which at 1000 HZ means
- * about once every 50 days. If that's actually a problem, one
- * could alternate squashing 0 to 1 and to -1.
- */
-
-#define MAKEVALID(x) (((x) == 0L) ? 1L : (x))
-#define ISVALID(x) ((x) != 0L)
-
-/*
- * Time comparison is subtle, as it's really truncated
- * modular arithmetic.
- */
-
-#define IS_SOONER(a, b, reference) \
- (((a) - (unsigned long)(reference)) < ((b) - (unsigned long)(reference)))
-
-/*
- * CATCHUP_INCREMENT, used when the function falls behind the counter.
- * Could be an increasing function instead of a constant;
- */
-
-#define CATCHUP_INCREMENT 64
-
-static int mips_next_event(unsigned long delta,
- struct clock_event_device *evt)
-{
- unsigned long flags;
- unsigned int mtflags;
- unsigned long timestamp, reference, previous;
- unsigned long nextcomp = 0L;
- int vpe = current_cpu_data.vpe_id;
- int cpu = smp_processor_id();
- local_irq_save(flags);
- mtflags = dmt();
-
- /*
- * Maintain the per-TC virtual timer
- * and program the per-VPE shared Count register
- * as appropriate here...
- */
- reference = (unsigned long)read_c0_count();
- timestamp = MAKEVALID(reference + delta);
- /*
- * To really model the clock, we have to catch the case
- * where the current next-in-VPE timestamp is the old
- * timestamp for the calling CPE, but the new value is
- * in fact later. In that case, we have to do a full
- * scan and discover the new next-in-VPE CPU id and
- * timestamp.
- */
- previous = smtc_nexttime[vpe][cpu];
- if (cpu == smtc_nextinvpe[vpe] && ISVALID(previous)
- && IS_SOONER(previous, timestamp, reference)) {
- int i;
- int soonest = cpu;
-
- /*
- * Update timestamp array here, so that new
- * value gets considered along with those of
- * other virtual CPUs on the VPE.
- */
- smtc_nexttime[vpe][cpu] = timestamp;
- for_each_online_cpu(i) {
- if (ISVALID(smtc_nexttime[vpe][i])
- && IS_SOONER(smtc_nexttime[vpe][i],
- smtc_nexttime[vpe][soonest], reference)) {
- soonest = i;
- }
- }
- smtc_nextinvpe[vpe] = soonest;
- nextcomp = smtc_nexttime[vpe][soonest];
- /*
- * Otherwise, we don't have to process the whole array rank,
- * we just have to see if the event horizon has gotten closer.
- */
- } else {
- if (!ISVALID(smtc_nexttime[vpe][smtc_nextinvpe[vpe]]) ||
- IS_SOONER(timestamp,
- smtc_nexttime[vpe][smtc_nextinvpe[vpe]], reference)) {
- smtc_nextinvpe[vpe] = cpu;
- nextcomp = timestamp;
- }
- /*
- * Since next-in-VPE may me the same as the executing
- * virtual CPU, we update the array *after* checking
- * its value.
- */
- smtc_nexttime[vpe][cpu] = timestamp;
- }
-
- /*
- * It may be that, in fact, we don't need to update Compare,
- * but if we do, we want to make sure we didn't fall into
- * a crack just behind Count.
- */
- if (ISVALID(nextcomp)) {
- write_c0_compare(nextcomp);
- ehb();
- /*
- * We never return an error, we just make sure
- * that we trigger the handlers as quickly as
- * we can if we fell behind.
- */
- while ((nextcomp - (unsigned long)read_c0_count())
- > (unsigned long)LONG_MAX) {
- nextcomp += CATCHUP_INCREMENT;
- write_c0_compare(nextcomp);
- ehb();
- }
- }
- emt(mtflags);
- local_irq_restore(flags);
- return 0;
-}
-
-
-void smtc_distribute_timer(int vpe)
-{
- unsigned long flags;
- unsigned int mtflags;
- int cpu;
- struct clock_event_device *cd;
- unsigned long nextstamp;
- unsigned long reference;
-
-
-repeat:
- nextstamp = 0L;
- for_each_online_cpu(cpu) {
- /*
- * Find virtual CPUs within the current VPE who have
- * unserviced timer requests whose time is now past.
- */
- local_irq_save(flags);
- mtflags = dmt();
- if (cpu_data[cpu].vpe_id == vpe &&
- ISVALID(smtc_nexttime[vpe][cpu])) {
- reference = (unsigned long)read_c0_count();
- if ((smtc_nexttime[vpe][cpu] - reference)
- > (unsigned long)LONG_MAX) {
- smtc_nexttime[vpe][cpu] = 0L;
- emt(mtflags);
- local_irq_restore(flags);
- /*
- * We don't send IPIs to ourself.
- */
- if (cpu != smp_processor_id()) {
- smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
- } else {
- cd = &per_cpu(mips_clockevent_device, cpu);
- cd->event_handler(cd);
- }
- } else {
- /* Local to VPE but Valid Time not yet reached. */
- if (!ISVALID(nextstamp) ||
- IS_SOONER(smtc_nexttime[vpe][cpu], nextstamp,
- reference)) {
- smtc_nextinvpe[vpe] = cpu;
- nextstamp = smtc_nexttime[vpe][cpu];
- }
- emt(mtflags);
- local_irq_restore(flags);
- }
- } else {
- emt(mtflags);
- local_irq_restore(flags);
-
- }
- }
- /* Reprogram for interrupt at next soonest timestamp for VPE */
- if (ISVALID(nextstamp)) {
- write_c0_compare(nextstamp);
- ehb();
- if ((nextstamp - (unsigned long)read_c0_count())
- > (unsigned long)LONG_MAX)
- goto repeat;
- }
-}
-
-
-irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
-{
- int cpu = smp_processor_id();
-
- /* If we're running SMTC, we've got MIPS MT and therefore MIPS32R2 */
- handle_perf_irq(1);
-
- if (read_c0_cause() & (1 << 30)) {
- /* Clear Count/Compare Interrupt */
- write_c0_compare(read_c0_compare());
- smtc_distribute_timer(cpu_data[cpu].vpe_id);
- }
- return IRQ_HANDLED;
-}
-
-
-int smtc_clockevent_init(void)
-{
- uint64_t mips_freq = mips_hpt_frequency;
- unsigned int cpu = smp_processor_id();
- struct clock_event_device *cd;
- unsigned int irq;
- int i;
- int j;
-
- if (!cpu_has_counter || !mips_hpt_frequency)
- return -ENXIO;
- if (cpu == 0) {
- for (i = 0; i < num_possible_cpus(); i++) {
- smtc_nextinvpe[i] = 0;
- for (j = 0; j < num_possible_cpus(); j++)
- smtc_nexttime[i][j] = 0L;
- }
- /*
- * SMTC also can't have the usablility test
- * run by secondary TCs once Compare is in use.
- */
- if (!c0_compare_int_usable())
- return -ENXIO;
- }
-
- /*
- * 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.
- */
- irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
- if (get_c0_compare_int)
- irq = get_c0_compare_int();
-
- cd = &per_cpu(mips_clockevent_device, cpu);
-
- cd->name = "MIPS";
- cd->features = CLOCK_EVT_FEAT_ONESHOT;
-
- /* Calculate the min / max delta */
- cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32);
- cd->shift = 32;
- cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
- cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
-
- cd->rating = 300;
- 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);
-
- /*
- * On SMTC we only want to do the data structure
- * initialization and IRQ setup once.
- */
- if (cpu)
- return 0;
- /*
- * And we need the hwmask associated with the c0_compare
- * vector to be initialized.
- */
- irq_hwmask[irq] = (0x100 << cp0_compare_irq);
- if (cp0_timer_irq_installed)
- return 0;
-
- cp0_timer_irq_installed = 1;
-
- setup_irq(irq, &c0_compare_irqaction);
-
- return 0;
-}
diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S
new file mode 100644
index 00000000000..6f4f739dad9
--- /dev/null
+++ b/arch/mips/kernel/cps-vec.S
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2013 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/asmmacro.h>
+#include <asm/cacheops.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#include <asm/pm.h>
+
+#define GCR_CL_COHERENCE_OFS 0x2008
+#define GCR_CL_ID_OFS 0x2028
+
+.extern mips_cm_base
+
+.set noreorder
+
+ /*
+ * 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
+ 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
+ .endm
+
+.section .text.cps-vec
+.balign 0x1000
+
+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.
+ */
+ .quad 0
+ .word 0
+
+ /* Check whether we're here due to an NMI */
+ mfc0 k0, CP0_STATUS
+ and k0, k0, ST0_NMI
+ beqz k0, not_nmi
+ nop
+
+ /* This is an NMI */
+ la k0, nmi_handler
+ jr k0
+ nop
+
+not_nmi:
+ /* Setup Cause */
+ li t0, CAUSEF_IV
+ mtc0 t0, CP0_CAUSE
+
+ /* Setup Status */
+ li t0, ST0_CU1 | ST0_CU0
+ mtc0 t0, CP0_STATUS
+
+ /*
+ * Clear the bits used to index the caches. Note that the architecture
+ * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
+ * be valid for all MIPS32 CPUs, even those for which said writes are
+ * unnecessary.
+ */
+ mtc0 zero, CP0_TAGLO, 0
+ mtc0 zero, CP0_TAGHI, 0
+ mtc0 zero, CP0_TAGLO, 2
+ mtc0 zero, CP0_TAGHI, 2
+ ehb
+
+ /* Primary cache configuration is indicated by Config1 */
+ mfc0 v0, CP0_CONFIG, 1
+
+ /* Detect I-cache line size */
+ _EXT t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
+ beqz t0, icache_done
+ li t1, 2
+ sllv t0, t1, t0
+
+ /* Detect I-cache size */
+ _EXT t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
+ xori t2, t1, 0x7
+ beqz t2, 1f
+ li t3, 32
+ addi t1, t1, 1
+ sllv t1, t3, t1
+1: /* At this point t1 == I-cache sets per way */
+ _EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
+ addi t2, t2, 1
+ mul t1, t1, t0
+ mul t1, t1, t2
+
+ li a0, KSEG0
+ add a1, a0, t1
+1: cache Index_Store_Tag_I, 0(a0)
+ add a0, a0, t0
+ bne a0, a1, 1b
+ nop
+icache_done:
+
+ /* Detect D-cache line size */
+ _EXT t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
+ beqz t0, dcache_done
+ li t1, 2
+ sllv t0, t1, t0
+
+ /* Detect D-cache size */
+ _EXT t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
+ xori t2, t1, 0x7
+ beqz t2, 1f
+ li t3, 32
+ addi t1, t1, 1
+ sllv t1, t3, t1
+1: /* At this point t1 == D-cache sets per way */
+ _EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
+ addi t2, t2, 1
+ mul t1, t1, t0
+ mul t1, t1, t2
+
+ li a0, KSEG0
+ addu a1, a0, t1
+ subu a1, a1, t0
+1: cache Index_Store_Tag_D, 0(a0)
+ bne a0, a1, 1b
+ add a0, a0, t0
+dcache_done:
+
+ /* Set Kseg0 CCA to that in s0 */
+ mfc0 t0, CP0_CONFIG
+ ori t0, 0x7
+ xori t0, 0x7
+ or t0, t0, s0
+ mtc0 t0, CP0_CONFIG
+ ehb
+
+ /* Enter the coherent domain */
+ li t0, 0xff
+ sw t0, GCR_CL_COHERENCE_OFS(v1)
+ ehb
+
+ /* Jump to kseg0 */
+ la t0, 1f
+ jr t0
+ nop
+
+ /*
+ * We're up, cached & coherent. Perform any further required core-level
+ * initialisation.
+ */
+1: jal mips_cps_core_init
+ nop
+
+ /*
+ * Boot any other VPEs within this core that should be online, and
+ * deactivate this VPE if it should be offline.
+ */
+ jal mips_cps_boot_vpes
+ nop
+
+ /* Off we go! */
+ lw t1, VPEBOOTCFG_PC(v0)
+ lw gp, VPEBOOTCFG_GP(v0)
+ lw sp, VPEBOOTCFG_SP(v0)
+ jr t1
+ nop
+ END(mips_cps_core_entry)
+
+.org 0x200
+LEAF(excep_tlbfill)
+ b .
+ nop
+ END(excep_tlbfill)
+
+.org 0x280
+LEAF(excep_xtlbfill)
+ b .
+ nop
+ END(excep_xtlbfill)
+
+.org 0x300
+LEAF(excep_cache)
+ b .
+ nop
+ END(excep_cache)
+
+.org 0x380
+LEAF(excep_genex)
+ b .
+ nop
+ END(excep_genex)
+
+.org 0x400
+LEAF(excep_intex)
+ b .
+ nop
+ END(excep_intex)
+
+.org 0x480
+LEAF(excep_ejtag)
+ la k0, ejtag_debug_handler
+ jr k0
+ nop
+ END(excep_ejtag)
+
+LEAF(mips_cps_core_init)
+#ifdef CONFIG_MIPS_MT
+ /* Check that the core implements the MT ASE */
+ has_mt t0, 3f
+ nop
+
+ .set push
+ .set mt
+
+ /* Only allow 1 TC per VPE to execute... */
+ dmt
+
+ /* ...and for the moment only 1 VPE */
+ dvpe
+ la t1, 1f
+ jr.hb t1
+ nop
+
+ /* Enter VPE configuration state */
+1: mfc0 t0, CP0_MVPCONTROL
+ ori t0, t0, MVPCONTROL_VPC
+ mtc0 t0, CP0_MVPCONTROL
+
+ /* Retrieve the number of VPEs within the core */
+ mfc0 t0, CP0_MVPCONF0
+ srl t0, t0, MVPCONF0_PVPE_SHIFT
+ andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
+ addi t7, t0, 1
+
+ /* If there's only 1, we're done */
+ beqz t0, 2f
+ nop
+
+ /* Loop through each VPE within this core */
+ li t5, 1
+
+1: /* Operate on the appropriate TC */
+ mtc0 t5, CP0_VPECONTROL
+ ehb
+
+ /* Bind TC to VPE (1:1 TC:VPE mapping) */
+ mttc0 t5, CP0_TCBIND
+
+ /* Set exclusive TC, non-active, master */
+ li t0, VPECONF0_MVP
+ sll t1, t5, VPECONF0_XTC_SHIFT
+ or t0, t0, t1
+ mttc0 t0, CP0_VPECONF0
+
+ /* Set TC non-active, non-allocatable */
+ mttc0 zero, CP0_TCSTATUS
+
+ /* Set TC halted */
+ li t0, TCHALT_H
+ mttc0 t0, CP0_TCHALT
+
+ /* Next VPE */
+ addi t5, t5, 1
+ slt t0, t5, t7
+ bnez t0, 1b
+ nop
+
+ /* Leave VPE configuration state */
+2: mfc0 t0, CP0_MVPCONTROL
+ xori t0, t0, MVPCONTROL_VPC
+ mtc0 t0, CP0_MVPCONTROL
+
+3: .set pop
+#endif
+ jr ra
+ nop
+ END(mips_cps_core_init)
+
+LEAF(mips_cps_boot_vpes)
+ /* Retrieve CM base address */
+ la t0, mips_cm_base
+ lw 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
+
+ /* Calculate this VPEs ID. If the core doesn't support MT use 0 */
+ has_mt t6, 1f
+ li t9, 0
+
+ /* Find the number of VPEs present in the core */
+ mfc0 t1, CP0_MVPCONF0
+ srl t1, t1, MVPCONF0_PVPE_SHIFT
+ andi t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
+ addi t1, t1, 1
+
+ /* Calculate a mask for the VPE ID from EBase.CPUNum */
+ clz t1, t1
+ li t2, 31
+ subu t1, t2, t1
+ li t2, 1
+ sll t1, t2, t1
+ addiu t1, t1, -1
+
+ /* Retrieve the VPE ID from EBase.CPUNum */
+ mfc0 t9, $15, 1
+ and t9, t9, t1
+
+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
+
+#ifdef CONFIG_MIPS_MT
+
+ /* If the core doesn't support MT then return */
+ bnez t6, 1f
+ nop
+ jr ra
+ nop
+
+ .set push
+ .set mt
+
+1: /* Enter VPE configuration state */
+ dvpe
+ la t1, 1f
+ jr.hb t1
+ nop
+1: mfc0 t1, CP0_MVPCONTROL
+ ori t1, t1, MVPCONTROL_VPC
+ mtc0 t1, CP0_MVPCONTROL
+ ehb
+
+ /* Loop through each VPE */
+ lw t6, COREBOOTCFG_VPEMASK(t0)
+ move t8, t6
+ li t5, 0
+
+ /* Check whether the VPE should be running. If not, skip it */
+1: andi t0, t6, 1
+ beqz t0, 2f
+ nop
+
+ /* Operate on the appropriate TC */
+ mfc0 t0, CP0_VPECONTROL
+ ori t0, t0, VPECONTROL_TARGTC
+ xori t0, t0, VPECONTROL_TARGTC
+ or t0, t0, t5
+ mtc0 t0, CP0_VPECONTROL
+ ehb
+
+ /* Skip the VPE if its TC is not halted */
+ mftc0 t0, CP0_TCHALT
+ beqz t0, 2f
+ nop
+
+ /* Calculate a pointer to the VPEs struct vpe_boot_config */
+ li t0, VPEBOOTCFG_SIZE
+ mul t0, t0, t5
+ addu t0, t0, t7
+
+ /* Set the TC restart PC */
+ lw t1, VPEBOOTCFG_PC(t0)
+ mttc0 t1, CP0_TCRESTART
+
+ /* Set the TC stack pointer */
+ lw t1, VPEBOOTCFG_SP(t0)
+ mttgpr t1, sp
+
+ /* Set the TC global pointer */
+ lw t1, VPEBOOTCFG_GP(t0)
+ mttgpr t1, gp
+
+ /* Copy config from this VPE */
+ mfc0 t0, CP0_CONFIG
+ mttc0 t0, CP0_CONFIG
+
+ /* Ensure no software interrupts are pending */
+ mttc0 zero, CP0_CAUSE
+ mttc0 zero, CP0_STATUS
+
+ /* Set TC active, not interrupt exempt */
+ mftc0 t0, CP0_TCSTATUS
+ li t1, ~TCSTATUS_IXMT
+ and t0, t0, t1
+ ori t0, t0, TCSTATUS_A
+ mttc0 t0, CP0_TCSTATUS
+
+ /* Clear the TC halt bit */
+ mttc0 zero, CP0_TCHALT
+
+ /* Set VPE active */
+ mftc0 t0, CP0_VPECONF0
+ ori t0, t0, VPECONF0_VPA
+ mttc0 t0, CP0_VPECONF0
+
+ /* Next VPE */
+2: srl t6, t6, 1
+ addi t5, t5, 1
+ bnez t6, 1b
+ nop
+
+ /* Leave VPE configuration state */
+ mfc0 t1, CP0_MVPCONTROL
+ xori t1, t1, MVPCONTROL_VPC
+ mtc0 t1, CP0_MVPCONTROL
+ ehb
+ evpe
+
+ /* Check whether this VPE is meant to be running */
+ li t0, 1
+ sll t0, t0, t9
+ and t0, t0, t8
+ bnez t0, 2f
+ nop
+
+ /* This VPE should be offline, halt the TC */
+ li t0, TCHALT_H
+ mtc0 t0, CP0_TCHALT
+ la t0, 1f
+1: jr.hb t0
+ nop
+
+2: .set pop
+
+#endif /* CONFIG_MIPS_MT */
+
+ /* Return */
+ jr ra
+ nop
+ END(mips_cps_boot_vpes)
+
+#if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM)
+
+ /* Calculate a pointer to this CPUs struct mips_static_suspend_state */
+ .macro psstate dest
+ .set push
+ .set noat
+ lw $1, TI_CPU(gp)
+ sll $1, $1, LONGLOG
+ la \dest, __per_cpu_offset
+ addu $1, $1, \dest
+ lw $1, 0($1)
+ la \dest, cps_cpu_state
+ addu \dest, \dest, $1
+ .set pop
+ .endm
+
+LEAF(mips_cps_pm_save)
+ /* Save CPU state */
+ SUSPEND_SAVE_REGS
+ psstate t1
+ SUSPEND_SAVE_STATIC
+ jr v0
+ nop
+ END(mips_cps_pm_save)
+
+LEAF(mips_cps_pm_restore)
+ /* Restore CPU state */
+ psstate t1
+ RESUME_RESTORE_STATIC
+ RESUME_RESTORE_REGS_RETURN
+ END(mips_cps_pm_restore)
+
+#endif /* CONFIG_MIPS_CPS_PM && CONFIG_CPU_PM */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 37663c7862a..d74f957c561 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -20,8 +20,11 @@
#include <asm/bugs.h>
#include <asm/cpu.h>
+#include <asm/cpu-type.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#include <asm/msa.h>
#include <asm/watch.h>
#include <asm/elf.h>
#include <asm/spram.h>
@@ -55,11 +58,11 @@ static inline void check_errata(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_34K:
/*
* Erratum "RPS May Cause Incorrect Instruction Execution"
- * This code only handles VPE0, any SMP/SMTC/RTOS code
+ * This code only handles VPE0, any SMP/RTOS code
* making use of VPE1 will be responsable for that VPE.
*/
if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
@@ -111,7 +114,7 @@ static inline unsigned long cpu_get_fpu_id(void)
unsigned long tmp, fpu_id;
tmp = read_c0_status();
- __enable_fpu();
+ __enable_fpu(FPU_AS_IS);
fpu_id = read_32bit_cp1_register(CP1_REVISION);
write_c0_status(tmp);
return fpu_id;
@@ -122,7 +125,21 @@ static inline unsigned long cpu_get_fpu_id(void)
*/
static inline int __cpu_has_fpu(void)
{
- return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
+ return ((cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE);
+}
+
+static inline unsigned long cpu_get_msa_id(void)
+{
+ unsigned long status, conf5, msa_id;
+
+ status = read_c0_status();
+ __enable_fpu(FPU_64BIT);
+ conf5 = read_c0_config5();
+ enable_msa();
+ msa_id = read_msa_ir();
+ write_c0_config5(conf5);
+ write_c0_status(status);
+ return msa_id;
}
static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
@@ -162,6 +179,27 @@ static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
static char unknown_isa[] = KERN_ERR \
"Unsupported ISA type, c0.config0: %d.";
+static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
+{
+ unsigned int config6;
+
+ /* 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();
+ if (enable)
+ /* Enable FTLB */
+ write_c0_config6(config6 | MIPS_CONF6_FTLBEN);
+ else
+ /* Disable FTLB */
+ write_c0_config6(config6 & ~MIPS_CONF6_FTLBEN);
+ back_to_back_c0_hazard();
+ break;
+ }
+}
+
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
{
unsigned int config0;
@@ -169,8 +207,13 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
config0 = read_c0_config();
- if (((config0 & MIPS_CONF_MT) >> 7) == 1)
+ /*
+ * Look for Standard TLB or Dual VTLB and FTLB
+ */
+ if ((((config0 & MIPS_CONF_MT) >> 7) == 1) ||
+ (((config0 & MIPS_CONF_MT) >> 7) == 4))
c->options |= MIPS_CPU_TLB;
+
isa = (config0 & MIPS_CONF_AT) >> 13;
switch (isa) {
case 0:
@@ -225,8 +268,11 @@ static inline unsigned int decode_config1(struct cpuinfo_mips *c)
c->options |= MIPS_CPU_FPU;
c->options |= MIPS_CPU_32FPR;
}
- if (cpu_has_tlb)
+ if (cpu_has_tlb) {
c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
+ c->tlbsizevtlb = c->tlbsize;
+ c->tlbsizeftlbsets = 0;
+ }
return config1 & MIPS_CONF_M;
}
@@ -271,6 +317,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
c->options |= MIPS_CPU_MICROMIPS;
if (config3 & MIPS_CONF3_VZ)
c->ases |= MIPS_ASE_VZ;
+ if (config3 & MIPS_CONF3_SC)
+ c->options |= MIPS_CPU_SEGMENTS;
+ if (config3 & MIPS_CONF3_MSA)
+ c->ases |= MIPS_ASE_MSA;
return config3 & MIPS_CONF_M;
}
@@ -278,18 +328,71 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
static inline unsigned int decode_config4(struct cpuinfo_mips *c)
{
unsigned int config4;
+ unsigned int newcf4;
+ unsigned int mmuextdef;
+ unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE;
config4 = read_c0_config4();
- if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
- && cpu_has_tlb)
- c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
+ if (cpu_has_tlb) {
+ if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
+ c->options |= MIPS_CPU_TLBINV;
+ mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+ switch (mmuextdef) {
+ case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
+ c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
+ c->tlbsizevtlb = c->tlbsize;
+ break;
+ case MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT:
+ c->tlbsizevtlb +=
+ ((config4 & MIPS_CONF4_VTLBSIZEEXT) >>
+ MIPS_CONF4_VTLBSIZEEXT_SHIFT) * 0x40;
+ c->tlbsize = c->tlbsizevtlb;
+ ftlb_page = MIPS_CONF4_VFTLBPAGESIZE;
+ /* fall through */
+ case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT:
+ newcf4 = (config4 & ~ftlb_page) |
+ (page_size_ftlb(mmuextdef) <<
+ MIPS_CONF4_FTLBPAGESIZE_SHIFT);
+ write_c0_config4(newcf4);
+ back_to_back_c0_hazard();
+ config4 = read_c0_config4();
+ if (config4 != newcf4) {
+ pr_err("PAGE_SIZE 0x%lx is not supported by FTLB (config4=0x%x)\n",
+ PAGE_SIZE, config4);
+ /* Switch FTLB off */
+ set_ftlb_enable(c, 0);
+ break;
+ }
+ c->tlbsizeftlbsets = 1 <<
+ ((config4 & MIPS_CONF4_FTLBSETS) >>
+ MIPS_CONF4_FTLBSETS_SHIFT);
+ c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >>
+ MIPS_CONF4_FTLBWAYS_SHIFT) + 2;
+ c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets;
+ break;
+ }
+ }
c->kscratch_mask = (config4 >> 16) & 0xff;
return config4 & MIPS_CONF_M;
}
+static inline unsigned int decode_config5(struct cpuinfo_mips *c)
+{
+ unsigned int config5;
+
+ config5 = read_c0_config5();
+ config5 &= ~MIPS_CONF5_UFR;
+ write_c0_config5(config5);
+
+ if (config5 & MIPS_CONF5_EVA)
+ c->options |= MIPS_CPU_EVA;
+
+ return config5 & MIPS_CONF_M;
+}
+
static void decode_configs(struct cpuinfo_mips *c)
{
int ok;
@@ -300,6 +403,9 @@ static void decode_configs(struct cpuinfo_mips *c)
c->scache.flags = MIPS_CACHE_NOT_PRESENT;
+ /* Enable FTLB if present */
+ set_ftlb_enable(c, 1);
+
ok = decode_config0(c); /* Read Config registers. */
BUG_ON(!ok); /* Arch spec violation! */
if (ok)
@@ -310,11 +416,18 @@ static void decode_configs(struct cpuinfo_mips *c)
ok = decode_config3(c);
if (ok)
ok = decode_config4(c);
+ if (ok)
+ ok = decode_config5(c);
mips_probe_watch_registers(c);
- if (cpu_has_mips_r2)
- c->core = read_c0_ebase() & 0x3ff;
+#ifndef CONFIG_MIPS_CPS
+ if (cpu_has_mips_r2) {
+ c->core = get_ebase_cpunum();
+ if (cpu_has_mipsmt)
+ c->core >>= fls(core_nvpes()) - 1;
+ }
+#endif
}
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
@@ -322,7 +435,7 @@ static void decode_configs(struct cpuinfo_mips *c)
static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
{
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_R2000:
c->cputype = CPU_R2000;
__cpu_name[cpu] = "R2000";
@@ -333,7 +446,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->tlbsize = 64;
break;
case PRID_IMP_R3000:
- if ((c->processor_id & 0xff) == PRID_REV_R3000A) {
+ if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
if (cpu_has_confreg()) {
c->cputype = CPU_R3081E;
__cpu_name[cpu] = "R3081";
@@ -353,7 +466,8 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
break;
case PRID_IMP_R4000:
if (read_c0_config() & CONF_SC) {
- if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
+ if ((c->processor_id & PRID_REV_MASK) >=
+ PRID_REV_R4400) {
c->cputype = CPU_R4400PC;
__cpu_name[cpu] = "R4400PC";
} else {
@@ -361,12 +475,33 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R4000PC";
}
} else {
- if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
- c->cputype = CPU_R4400SC;
- __cpu_name[cpu] = "R4400SC";
+ int cca = read_c0_config() & CONF_CM_CMASK;
+ int mc;
+
+ /*
+ * SC and MC versions can't be reliably told apart,
+ * but only the latter support coherent caching
+ * modes so assume the firmware has set the KSEG0
+ * coherency attribute reasonably (if uncached, we
+ * assume SC).
+ */
+ switch (cca) {
+ case CONF_CM_CACHABLE_CE:
+ case CONF_CM_CACHABLE_COW:
+ case CONF_CM_CACHABLE_CUW:
+ mc = 1;
+ break;
+ default:
+ mc = 0;
+ break;
+ }
+ if ((c->processor_id & PRID_REV_MASK) >=
+ PRID_REV_R4400) {
+ c->cputype = mc ? CPU_R4400MC : CPU_R4400SC;
+ __cpu_name[cpu] = mc ? "R4400MC" : "R4400SC";
} else {
- c->cputype = CPU_R4000SC;
- __cpu_name[cpu] = "R4000SC";
+ c->cputype = mc ? CPU_R4000MC : CPU_R4000SC;
+ __cpu_name[cpu] = mc ? "R4000MC" : "R4000SC";
}
}
@@ -454,7 +589,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "TX3927";
c->tlbsize = 64;
} else {
- switch (c->processor_id & 0xff) {
+ switch (c->processor_id & PRID_REV_MASK) {
case PRID_REV_TX3912:
c->cputype = CPU_TX3912;
__cpu_name[cpu] = "TX3912";
@@ -549,21 +684,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
*/
c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
break;
- case PRID_IMP_RM9000:
- c->cputype = CPU_RM9000;
- __cpu_name[cpu] = "RM9000";
- set_isa(c, MIPS_CPU_ISA_IV);
- c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
- MIPS_CPU_LLSC;
- /*
- * Bit 29 in the info register of the RM9000
- * indicates if the TLB has 48 or 64 entries.
- *
- * 29 1 => 64 entry JTLB
- * 0 => 48 entry JTLB
- */
- c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
- break;
case PRID_IMP_R8000:
c->cputype = CPU_R8000;
__cpu_name[cpu] = "RM8000";
@@ -603,17 +723,23 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_LLSC;
c->tlbsize = 64;
break;
- case PRID_IMP_LOONGSON2:
- c->cputype = CPU_LOONGSON2;
- __cpu_name[cpu] = "ICT Loongson-2";
-
+ case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */
switch (c->processor_id & PRID_REV_MASK) {
case PRID_REV_LOONGSON2E:
+ c->cputype = CPU_LOONGSON2;
+ __cpu_name[cpu] = "ICT Loongson-2";
set_elf_platform(cpu, "loongson2e");
break;
case PRID_REV_LOONGSON2F:
+ c->cputype = CPU_LOONGSON2;
+ __cpu_name[cpu] = "ICT Loongson-2";
set_elf_platform(cpu, "loongson2f");
break;
+ case PRID_REV_LOONGSON3A:
+ c->cputype = CPU_LOONGSON3;
+ __cpu_name[cpu] = "ICT Loongson-3";
+ set_elf_platform(cpu, "loongson3a");
+ break;
}
set_isa(c, MIPS_CPU_ISA_III);
@@ -622,7 +748,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_32FPR;
c->tlbsize = 64;
break;
- case PRID_IMP_LOONGSON1:
+ case PRID_IMP_LOONGSON_32: /* Loongson-1 */
decode_configs(c);
c->cputype = CPU_LOONGSON1;
@@ -639,8 +765,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
{
- decode_configs(c);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_4KC:
c->cputype = CPU_4KC;
__cpu_name[cpu] = "MIPS 4Kc";
@@ -700,18 +825,44 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "MIPS 1004Kc";
break;
case PRID_IMP_1074K:
- c->cputype = CPU_74K;
+ c->cputype = CPU_1074K;
__cpu_name[cpu] = "MIPS 1074Kc";
break;
+ case PRID_IMP_INTERAPTIV_UP:
+ c->cputype = CPU_INTERAPTIV;
+ __cpu_name[cpu] = "MIPS interAptiv";
+ break;
+ case PRID_IMP_INTERAPTIV_MP:
+ c->cputype = CPU_INTERAPTIV;
+ __cpu_name[cpu] = "MIPS interAptiv (multi)";
+ break;
+ case PRID_IMP_PROAPTIV_UP:
+ c->cputype = CPU_PROAPTIV;
+ __cpu_name[cpu] = "MIPS proAptiv";
+ break;
+ case PRID_IMP_PROAPTIV_MP:
+ c->cputype = CPU_PROAPTIV;
+ __cpu_name[cpu] = "MIPS proAptiv (multi)";
+ break;
+ case PRID_IMP_P5600:
+ c->cputype = CPU_P5600;
+ __cpu_name[cpu] = "MIPS P5600";
+ break;
+ case PRID_IMP_M5150:
+ c->cputype = CPU_M5150;
+ __cpu_name[cpu] = "MIPS M5150";
+ break;
}
+ decode_configs(c);
+
spram_config();
}
static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_AU1_REV1:
case PRID_IMP_AU1_REV2:
c->cputype = CPU_ALCHEMY;
@@ -730,7 +881,7 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
break;
case 4:
__cpu_name[cpu] = "Au1200";
- if ((c->processor_id & 0xff) == 2)
+ if ((c->processor_id & PRID_REV_MASK) == 2)
__cpu_name[cpu] = "Au1250";
break;
case 5:
@@ -748,12 +899,12 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_SB1:
c->cputype = CPU_SB1;
__cpu_name[cpu] = "SiByte SB1";
/* FPU in pass1 is known to have issues. */
- if ((c->processor_id & 0xff) < 0x02)
+ if ((c->processor_id & PRID_REV_MASK) < 0x02)
c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
break;
case PRID_IMP_SB1A:
@@ -766,7 +917,7 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_SR71000:
c->cputype = CPU_SR71000;
__cpu_name[cpu] = "Sandcraft SR71000";
@@ -779,7 +930,7 @@ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_PR4450:
c->cputype = CPU_PR4450;
__cpu_name[cpu] = "Philips PR4450";
@@ -791,7 +942,7 @@ static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_BMIPS32_REV4:
case PRID_IMP_BMIPS32_REV8:
c->cputype = CPU_BMIPS32;
@@ -806,7 +957,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
set_elf_platform(cpu, "bmips3300");
break;
case PRID_IMP_BMIPS43XX: {
- int rev = c->processor_id & 0xff;
+ int rev = c->processor_id & PRID_REV_MASK;
if (rev >= PRID_REV_BMIPS4380_LO &&
rev <= PRID_REV_BMIPS4380_HI) {
@@ -832,7 +983,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_CAVIUM_CN38XX:
case PRID_IMP_CAVIUM_CN31XX:
case PRID_IMP_CAVIUM_CN30XX:
@@ -875,7 +1026,8 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
decode_configs(c);
/* JZRISC does not implement the CP0 counter. */
c->options &= ~MIPS_CPU_COUNTER;
- switch (c->processor_id & 0xff00) {
+ BUG_ON(!__builtin_constant_p(cpu_has_counter) || cpu_has_counter);
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_JZRISC:
c->cputype = CPU_JZRISC;
__cpu_name[cpu] = "Ingenic JZRISC";
@@ -890,7 +1042,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
{
decode_configs(c);
- if ((c->processor_id & 0xff00) == PRID_IMP_NETLOGIC_AU13XX) {
+ if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_NETLOGIC_AU13XX) {
c->cputype = CPU_ALCHEMY;
__cpu_name[cpu] = "Au1300";
/* following stuff is not for Alchemy */
@@ -905,8 +1057,10 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
MIPS_CPU_EJTAG |
MIPS_CPU_LLSC);
- switch (c->processor_id & 0xff00) {
+ switch (c->processor_id & PRID_IMP_MASK) {
case PRID_IMP_NETLOGIC_XLP2XX:
+ case PRID_IMP_NETLOGIC_XLP9XX:
+ case PRID_IMP_NETLOGIC_XLP5XX:
c->cputype = CPU_XLP;
__cpu_name[cpu] = "Broadcom XLPII";
break;
@@ -984,7 +1138,7 @@ void cpu_probe(void)
c->cputype = CPU_UNKNOWN;
c->processor_id = read_c0_prid();
- switch (c->processor_id & 0xff0000) {
+ switch (c->processor_id & PRID_COMP_MASK) {
case PRID_COMP_LEGACY:
cpu_probe_legacy(c, cpu);
break;
@@ -1051,6 +1205,12 @@ void cpu_probe(void)
else
c->srsets = 1;
+ if (cpu_has_msa) {
+ c->msa_id = cpu_get_msa_id();
+ WARN(c->msa_id & MSA_IR_WRPF,
+ "Vector register partitioning unimplemented!");
+ }
+
cpu_probe_vmbits(c);
#ifdef CONFIG_64BIT
@@ -1063,8 +1223,10 @@ void cpu_report(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
- printk(KERN_INFO "CPU revision is: %08x (%s)\n",
- c->processor_id, cpu_name_string());
+ pr_info("CPU%d revision is: %08x (%s)\n",
+ smp_processor_id(), c->processor_id, cpu_name_string());
if (c->options & MIPS_CPU_FPU)
printk(KERN_INFO "FPU revision is: %08x\n", c->fpu_id);
+ if (cpu_has_msa)
+ pr_info("MSA revision is: %08x\n", c->msa_id);
}
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
index 93aa302948d..d21264681e9 100644
--- a/arch/mips/kernel/crash.c
+++ b/arch/mips/kernel/crash.c
@@ -5,7 +5,6 @@
#include <linux/bootmem.h>
#include <linux/crash_dump.h>
#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/sched.h>
diff --git a/arch/mips/kernel/csrc-powertv.c b/arch/mips/kernel/csrc-powertv.c
deleted file mode 100644
index abd99ea911a..00000000000
--- a/arch/mips/kernel/csrc-powertv.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2008 Scientific-Atlanta, 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-/*
- * The file comes from kernel/csrc-r4k.c
- */
-#include <linux/clocksource.h>
-#include <linux/init.h>
-
-#include <asm/time.h> /* Not included in linux/time.h */
-
-#include <asm/mach-powertv/asic_regs.h>
-#include "powertv-clock.h"
-
-/* MIPS PLL Register Definitions */
-#define PLL_GET_M(x) (((x) >> 8) & 0x000000FF)
-#define PLL_GET_N(x) (((x) >> 16) & 0x000000FF)
-#define PLL_GET_P(x) (((x) >> 24) & 0x00000007)
-
-/*
- * returns: Clock frequency in kHz
- */
-unsigned int __init mips_get_pll_freq(void)
-{
- unsigned int pll_reg, m, n, p;
- unsigned int fin = 54000; /* Base frequency in kHz */
- unsigned int fout;
-
- /* Read PLL register setting */
- pll_reg = asic_read(mips_pll_setup);
- m = PLL_GET_M(pll_reg);
- n = PLL_GET_N(pll_reg);
- p = PLL_GET_P(pll_reg);
- pr_info("MIPS PLL Register:0x%x M=%d N=%d P=%d\n", pll_reg, m, n, p);
-
- /* Calculate clock frequency = (2 * N * 54MHz) / (M * (2**P)) */
- fout = ((2 * n * fin) / (m * (0x01 << p)));
-
- pr_info("MIPS Clock Freq=%d kHz\n", fout);
-
- return fout;
-}
-
-static cycle_t c0_hpt_read(struct clocksource *cs)
-{
- return read_c0_count();
-}
-
-static struct clocksource clocksource_mips = {
- .name = "powertv-counter",
- .read = c0_hpt_read,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static void __init powertv_c0_hpt_clocksource_init(void)
-{
- unsigned int pll_freq = mips_get_pll_freq();
-
- pr_info("CPU frequency %d.%02d MHz\n", pll_freq / 1000,
- (pll_freq % 1000) * 100 / 1000);
-
- mips_hpt_frequency = pll_freq / 2 * 1000;
-
- clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
-
- clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
-}
-
-/**
- * struct tim_c - free running counter
- * @hi: High 16 bits of the counter
- * @lo: Low 32 bits of the counter
- *
- * Lays out the structure of the free running counter in memory. This counter
- * increments at a rate of 27 MHz/8 on all platforms.
- */
-struct tim_c {
- unsigned int hi;
- unsigned int lo;
-};
-
-static struct tim_c *tim_c;
-
-static cycle_t tim_c_read(struct clocksource *cs)
-{
- unsigned int hi;
- unsigned int next_hi;
- unsigned int lo;
-
- hi = readl(&tim_c->hi);
-
- for (;;) {
- lo = readl(&tim_c->lo);
- next_hi = readl(&tim_c->hi);
- if (next_hi == hi)
- break;
- hi = next_hi;
- }
-
-pr_crit("%s: read %llx\n", __func__, ((u64) hi << 32) | lo);
- return ((u64) hi << 32) | lo;
-}
-
-#define TIM_C_SIZE 48 /* # bits in the timer */
-
-static struct clocksource clocksource_tim_c = {
- .name = "powertv-tim_c",
- .read = tim_c_read,
- .mask = CLOCKSOURCE_MASK(TIM_C_SIZE),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/**
- * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
- *
- * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
- * 1 / (27,000,000/8) seconds.
- */
-static void __init powertv_tim_c_clocksource_init(void)
-{
- const unsigned long counts_per_second = 27000000 / 8;
-
- clocksource_tim_c.rating = 200;
-
- clocksource_register_hz(&clocksource_tim_c, counts_per_second);
- tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
-}
-
-/**
- powertv_clocksource_init - initialize all clocksources
- */
-void __init powertv_clocksource_init(void)
-{
- powertv_c0_hpt_clocksource_init();
- powertv_tim_c_clocksource_init();
-}
diff --git a/arch/mips/kernel/early_printk_8250.c b/arch/mips/kernel/early_printk_8250.c
new file mode 100644
index 00000000000..83cea376755
--- /dev/null
+++ b/arch/mips/kernel/early_printk_8250.c
@@ -0,0 +1,66 @@
+/*
+ * 8250/16550-type serial ports prom_putchar()
+ *
+ * Copyright (C) 2010 Yoichi Yuasa <yuasa@linux-mips.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/io.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+static void __iomem *serial8250_base;
+static unsigned int serial8250_reg_shift;
+static unsigned int serial8250_tx_timeout;
+
+void setup_8250_early_printk_port(unsigned long base, unsigned int reg_shift,
+ unsigned int timeout)
+{
+ serial8250_base = (void __iomem *)base;
+ serial8250_reg_shift = reg_shift;
+ serial8250_tx_timeout = timeout;
+}
+
+static inline u8 serial_in(int offset)
+{
+ return readb(serial8250_base + (offset << serial8250_reg_shift));
+}
+
+static inline void serial_out(int offset, char value)
+{
+ writeb(value, serial8250_base + (offset << serial8250_reg_shift));
+}
+
+void prom_putchar(char c)
+{
+ unsigned int timeout;
+ int status, bits;
+
+ if (!serial8250_base)
+ return;
+
+ timeout = serial8250_tx_timeout;
+ bits = UART_LSR_TEMT | UART_LSR_THRE;
+
+ do {
+ status = serial_in(UART_LSR);
+
+ if (--timeout == 0)
+ break;
+ } while ((status & bits) != bits);
+
+ if (timeout)
+ serial_out(UART_TX, c);
+}
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index e5786858cdb..4353d323f01 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -16,9 +16,6 @@
#include <asm/isadep.h>
#include <asm/thread_info.h>
#include <asm/war.h>
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/mipsmtregs.h>
-#endif
#ifndef CONFIG_PREEMPT
#define resume_kernel restore_all
@@ -89,41 +86,6 @@ FEXPORT(syscall_exit)
bnez t0, syscall_exit_work
restore_all: # restore full frame
-#ifdef CONFIG_MIPS_MT_SMTC
-#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
-/* Re-arm any temporarily masked interrupts not explicitly "acked" */
- mfc0 v0, CP0_TCSTATUS
- ori v1, v0, TCSTATUS_IXMT
- mtc0 v1, CP0_TCSTATUS
- andi v0, TCSTATUS_IXMT
- _ehb
- mfc0 t0, CP0_TCCONTEXT
- DMT 9 # dmt t1
- jal mips_ihb
- mfc0 t2, CP0_STATUS
- andi t3, t0, 0xff00
- or t2, t2, t3
- mtc0 t2, CP0_STATUS
- _ehb
- andi t1, t1, VPECONTROL_TE
- beqz t1, 1f
- EMT
-1:
- mfc0 v1, CP0_TCSTATUS
- /* We set IXMT above, XOR should clear it here */
- xori v1, v1, TCSTATUS_IXMT
- or v1, v0, v1
- mtc0 v1, CP0_TCSTATUS
- _ehb
- xor t0, t0, t3
- mtc0 t0, CP0_TCCONTEXT
-#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
-/* Detect and execute deferred IPI "interrupts" */
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
- jal deferred_smtc_ipi
- LONG_S s0, TI_REGS($28)
-#endif /* CONFIG_MIPS_MT_SMTC */
.set noat
RESTORE_TEMP
RESTORE_AT
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index dba90ec0dc3..60e7e5e45af 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -11,11 +11,14 @@
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/ftrace.h>
+#include <linux/syscalls.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/cacheflush.h>
+#include <asm/syscall.h>
#include <asm/uasm.h>
+#include <asm/unistd.h>
#include <asm-generic/sections.h>
@@ -87,6 +90,7 @@ static inline void ftrace_dyn_arch_init_insns(void)
static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
{
int faulted;
+ mm_segment_t old_fs;
/* *(unsigned int *)ip = new_code; */
safe_store_code(new_code, ip, faulted);
@@ -94,7 +98,10 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
if (unlikely(faulted))
return -EFAULT;
+ old_fs = get_fs();
+ set_fs(get_ds());
flush_icache_range(ip, ip + 8);
+ set_fs(old_fs);
return 0;
}
@@ -108,11 +115,10 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
safe_store_code(new_code1, ip, faulted);
if (unlikely(faulted))
return -EFAULT;
- ip += 4;
- safe_store_code(new_code2, ip, faulted);
+ safe_store_code(new_code2, ip + 4, faulted);
if (unlikely(faulted))
return -EFAULT;
- flush_icache_range(ip, ip + 8); /* original ip + 12 */
+ flush_icache_range(ip, ip + 8);
return 0;
}
#endif
@@ -195,7 +201,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
return ftrace_modify_code(FTRACE_CALL_IP, new);
}
-int __init ftrace_dyn_arch_init(void *data)
+int __init ftrace_dyn_arch_init(void)
{
/* Encode the instructions when booting */
ftrace_dyn_arch_init_insns();
@@ -203,9 +209,6 @@ int __init ftrace_dyn_arch_init(void *data)
/* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */
ftrace_modify_code(MCOUNT_ADDR, INSN_NOP);
- /* The return code is retured via data */
- *(unsigned long *)data = 0;
-
return 0;
}
#endif /* CONFIG_DYNAMIC_FTRACE */
@@ -364,3 +367,33 @@ out:
WARN_ON(1);
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+#ifdef CONFIG_32BIT
+unsigned long __init arch_syscall_addr(int nr)
+{
+ return (unsigned long)sys_call_table[nr - __NR_O32_Linux];
+}
+#endif
+
+#ifdef CONFIG_64BIT
+
+unsigned long __init arch_syscall_addr(int nr)
+{
+#ifdef CONFIG_MIPS32_N32
+ if (nr >= __NR_N32_Linux && nr <= __NR_N32_Linux + __NR_N32_Linux_syscalls)
+ return (unsigned long)sysn32_call_table[nr - __NR_N32_Linux];
+#endif
+ if (nr >= __NR_64_Linux && nr <= __NR_64_Linux + __NR_64_Linux_syscalls)
+ return (unsigned long)sys_call_table[nr - __NR_64_Linux];
+#ifdef CONFIG_MIPS32_O32
+ if (nr >= __NR_O32_Linux && nr <= __NR_O32_Linux + __NR_O32_Linux_syscalls)
+ return (unsigned long)sys32_call_table[nr - __NR_O32_Linux];
+#endif
+
+ return (unsigned long) &sys_ni_syscall;
+}
+#endif
+
+#endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 31fa856829c..ac35e12cb1f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -21,20 +21,6 @@
#include <asm/war.h>
#include <asm/thread_info.h>
-#ifdef CONFIG_MIPS_MT_SMTC
-#define PANIC_PIC(msg) \
- .set push; \
- .set nomicromips; \
- .set reorder; \
- PTR_LA a0,8f; \
- .set noat; \
- PTR_LA AT, panic; \
- jr AT; \
-9: b 9b; \
- .set pop; \
- TEXT(msg)
-#endif
-
__INIT
/*
@@ -67,7 +53,7 @@ NESTED(except_vec3_generic, 0, sp)
*/
NESTED(except_vec3_r4000, 0, sp)
.set push
- .set mips3
+ .set arch=r4000
.set noat
mfc0 k1, CP0_CAUSE
li k0, 31<<2
@@ -139,7 +125,7 @@ LEAF(__r4k_wait)
nop
nop
#endif
- .set mips3
+ .set arch=r4000
wait
/* end of rollback region (the region size must be power of two) */
1:
@@ -251,15 +237,6 @@ NESTED(except_vec_vi, 0, sp)
SAVE_AT
.set push
.set noreorder
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * To keep from blindly blocking *all* interrupts
- * during service by SMTC kernel, we also want to
- * pass the IM value to be cleared.
- */
-FEXPORT(except_vec_vi_mori)
- ori a0, $0, 0
-#endif /* CONFIG_MIPS_MT_SMTC */
PTR_LA v1, except_vec_vi_handler
FEXPORT(except_vec_vi_lui)
lui v0, 0 /* Patched */
@@ -277,37 +254,10 @@ EXPORT(except_vec_vi_end)
NESTED(except_vec_vi_handler, 0, sp)
SAVE_TEMP
SAVE_STATIC
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC has an interesting problem that interrupts are level-triggered,
- * and the CLI macro will clear EXL, potentially causing a duplicate
- * interrupt service invocation. So we need to clear the associated
- * IM bit of Status prior to doing CLI, and restore it after the
- * service routine has been invoked - we must assume that the
- * service routine will have cleared the state, and any active
- * level represents a new or otherwised unserviced event...
- */
- mfc0 t1, CP0_STATUS
- and t0, a0, t1
-#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
- mfc0 t2, CP0_TCCONTEXT
- or t2, t0, t2
- mtc0 t2, CP0_TCCONTEXT
-#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
- xor t1, t1, t0
- mtc0 t1, CP0_STATUS
- _ehb
-#endif /* CONFIG_MIPS_MT_SMTC */
CLI
#ifdef CONFIG_TRACE_IRQFLAGS
move s0, v0
-#ifdef CONFIG_MIPS_MT_SMTC
- move s1, a0
-#endif
TRACE_IRQS_OFF
-#ifdef CONFIG_MIPS_MT_SMTC
- move a0, s1
-#endif
move v0, s0
#endif
@@ -374,12 +324,20 @@ NESTED(except_vec_nmi, 0, sp)
NESTED(nmi_handler, PT_SIZE, sp)
.set push
.set noat
+ /*
+ * Clear ERL - restore segment mapping
+ * Clear BEV - required for page fault exception handler to work
+ */
+ mfc0 k0, CP0_STATUS
+ ori k0, k0, ST0_EXL
+ li k1, ~(ST0_BEV | ST0_ERL)
+ and k0, k0, k1
+ mtc0 k0, CP0_STATUS
+ _ehb
SAVE_ALL
move a0, sp
jal nmi_exception_handler
- RESTORE_ALL
- .set mips3
- eret
+ /* nmi_exception_handler never returns */
.set pop
END(nmi_handler)
@@ -467,7 +425,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER cpu cpu sti silent /* #11 */
BUILD_HANDLER ov ov sti silent /* #12 */
BUILD_HANDLER tr tr sti silent /* #13 */
+ BUILD_HANDLER msa_fpe msa_fpe sti silent /* #14 */
BUILD_HANDLER fpe fpe fpe silent /* #15 */
+ BUILD_HANDLER ftlb ftlb none silent /* #16 */
+ BUILD_HANDLER msa msa sti silent /* #21 */
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
#ifdef CONFIG_HARDWARE_WATCHPOINTS
/*
@@ -485,9 +446,6 @@ NESTED(nmi_handler, PT_SIZE, sp)
.align 5
LEAF(handle_ri_rdhwr_vivt)
-#ifdef CONFIG_MIPS_MT_SMTC
- PANIC_PIC("handle_ri_rdhwr_vivt called")
-#else
.set push
.set noat
.set noreorder
@@ -506,7 +464,6 @@ NESTED(nmi_handler, PT_SIZE, sp)
.set pop
bltz k1, handle_ri /* slow path */
/* fall thru */
-#endif
END(handle_ri_rdhwr_vivt)
LEAF(handle_ri_rdhwr)
@@ -566,7 +523,7 @@ isrdhwr:
ori k1, _THREAD_MASK
xori k1, _THREAD_MASK
LONG_L v1, TI_TP_VALUE(k1)
- .set mips3
+ .set arch=r4000
eret
.set mips0
#endif
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 7b6a5b3e3ac..95afd663cd4 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -35,33 +35,12 @@
*/
.macro setup_c0_status set clr
.set push
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * For SMTC, we need to set privilege and disable interrupts only for
- * the current TC, using the TCStatus register.
- */
- mfc0 t0, CP0_TCSTATUS
- /* Fortunately CU 0 is in the same place in both registers */
- /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
- li t1, ST0_CU0 | 0x08001c00
- or t0, t1
- /* Clear TKSU, leave IXMT */
- xori t0, 0x00001800
- mtc0 t0, CP0_TCSTATUS
- _ehb
- /* We need to leave the global IE bit set, but clear EXL...*/
- mfc0 t0, CP0_STATUS
- or t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr
- xor t0, ST0_EXL | ST0_ERL | \clr
- mtc0 t0, CP0_STATUS
-#else
mfc0 t0, CP0_STATUS
or t0, ST0_CU0|\set|0x1f|\clr
xor t0, 0x1f|\clr
mtc0 t0, CP0_STATUS
.set noreorder
sll zero,3 # ehb
-#endif
.set pop
.endm
@@ -115,24 +94,6 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
jr t0
0:
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * In SMTC kernel, "CLI" is thread-specific, in TCStatus.
- * We still need to enable interrupts globally in Status,
- * and clear EXL/ERL.
- *
- * TCContext is used to track interrupt levels under
- * service in SMTC kernel. Clear for boot TC before
- * allowing any interrupts.
- */
- mtc0 zero, CP0_TCCONTEXT
-
- mfc0 t0, CP0_STATUS
- ori t0, t0, 0xff1f
- xori t0, t0, 0x001e
- mtc0 t0, CP0_STATUS
-#endif /* CONFIG_MIPS_MT_SMTC */
-
PTR_LA t0, __bss_start # clear .bss
LONG_S zero, (t0)
PTR_LA t1, __bss_stop - LONGSIZE
@@ -164,25 +125,8 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
* function after setting up the stack and gp registers.
*/
NESTED(smp_bootstrap, 16, sp)
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * Read-modify-writes of Status must be atomic, and this
- * is one case where CLI is invoked without EXL being
- * necessarily set. The CLI and setup_c0_status will
- * in fact be redundant for all but the first TC of
- * each VPE being booted.
- */
- DMT 10 # dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */
- jal mips_ihb
-#endif /* CONFIG_MIPS_MT_SMTC */
- setup_c0_status_sec
smp_slave_setup
-#ifdef CONFIG_MIPS_MT_SMTC
- andi t2, t2, VPECONTROL_TE
- beqz t2, 2f
- EMT # emt
-2:
-#endif /* CONFIG_MIPS_MT_SMTC */
+ setup_c0_status_sec
j start_secondary
END(smp_bootstrap)
#endif /* CONFIG_SMP */
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 2b91fe80c43..50b364897dd 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -42,9 +42,6 @@ static struct irq_chip i8259A_chip = {
.irq_disable = disable_8259A_irq,
.irq_unmask = enable_8259A_irq,
.irq_mask_ack = mask_and_ack_8259A,
-#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
- .irq_set_affinity = plat_set_irq_affinity,
-#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
};
/*
@@ -180,7 +177,6 @@ handle_real_irq:
outb(cached_master_mask, PIC_MASTER_IMR);
outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */
}
- smtc_im_ack_irq(irq);
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
return;
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index 42f8875d244..09ce4598075 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <asm/cpu.h>
#include <asm/cpu-info.h>
+#include <asm/cpu-type.h>
#include <asm/idle.h>
#include <asm/mipsregs.h>
@@ -63,7 +64,7 @@ void r4k_wait_irqoff(void)
if (!need_resched())
__asm__(
" .set push \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" wait \n"
" .set pop \n");
local_irq_enable();
@@ -81,7 +82,7 @@ static void rm7k_wait_irqoff(void)
if (!need_resched())
__asm__(
" .set push \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" .set noat \n"
" mfc0 $1, $12 \n"
" sync \n"
@@ -102,7 +103,7 @@ static void au1k_wait(void)
unsigned long c0status = read_c0_status() | 1; /* irqs on */
__asm__(
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" cache 0x14, 0(%0) \n"
" cache 0x14, 32(%0) \n"
" sync \n"
@@ -136,7 +137,7 @@ void __init check_wait(void)
return;
}
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_R3081:
case CPU_R3081E:
cpu_wait = r3081_wait;
@@ -183,6 +184,11 @@ void __init check_wait(void)
case CPU_24K:
case CPU_34K:
case CPU_1004K:
+ case CPU_1074K:
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ case CPU_P5600:
+ case CPU_M5150:
cpu_wait = r4k_wait;
if (read_c0_config7() & MIPS_CONF7_WII)
cpu_wait = r4k_wait_irqoff;
@@ -218,29 +224,26 @@ void __init check_wait(void)
cpu_wait = r4k_wait;
*/
break;
- case CPU_RM9000:
- if ((c->processor_id & 0x00ff) >= 0x40)
- cpu_wait = r4k_wait;
- break;
default:
break;
}
}
-static void smtc_idle_hook(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_idle_loop_hook(void);
-
- smtc_idle_loop_hook();
-#endif
-}
-
void arch_cpu_idle(void)
{
- smtc_idle_hook();
if (cpu_wait)
cpu_wait();
else
local_irq_enable();
}
+
+#ifdef CONFIG_CPU_IDLE
+
+int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ arch_cpu_idle();
+ return index;
+}
+
+#endif
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index 5b5ddb231f2..88e4c323382 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -16,7 +16,6 @@
#include <asm/gic.h>
#include <asm/setup.h>
#include <asm/traps.h>
-#include <asm/gcmpregs.h>
#include <linux/hardirq.h>
#include <asm-generic/bitops/find.h>
@@ -55,6 +54,21 @@ void gic_write_compare(cycle_t cnt)
(int)(cnt & 0xffffffff));
}
+void gic_write_cpu_compare(cycle_t cnt, int cpu)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+ (int)(cnt >> 32));
+ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+ (int)(cnt & 0xffffffff));
+
+ local_irq_restore(flags);
+}
+
cycle_t gic_read_compare(void)
{
unsigned int hi, lo;
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index fab40f7d2e0..a734b2c2f9e 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -53,13 +53,9 @@ static inline void unmask_msc_irq(struct irq_data *d)
*/
static void level_mask_and_ack_msc_irq(struct irq_data *d)
{
- unsigned int irq = d->irq;
-
mask_msc_irq(d);
if (!cpu_has_veic)
MSCIC_WRITE(MSC01_IC_EOI, 0);
- /* This actually needs to be a call into platform code */
- smtc_im_ack_irq(irq);
}
/*
@@ -78,7 +74,6 @@ static void edge_mask_and_ack_msc_irq(struct irq_data *d)
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
}
- smtc_im_ack_irq(irq);
}
/*
@@ -131,7 +126,7 @@ void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqma
board_bind_eic_interrupt = &msc_bind_eic_interrupt;
- for (; nirq >= 0; nirq--, imp++) {
+ for (; nirq > 0; nirq--, imp++) {
int n = imp->im_irq;
switch (imp->im_type) {
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index d1fea7a054b..d2bfbc2e899 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -62,9 +62,9 @@ void __init alloc_legacy_irqno(void)
void free_irqno(unsigned int irq)
{
- smp_mb__before_clear_bit();
+ smp_mb__before_atomic();
clear_bit(irq, irq_map);
- smp_mb__after_clear_bit();
+ smp_mb__after_atomic();
}
/*
@@ -73,7 +73,6 @@ void free_irqno(unsigned int irq)
*/
void ack_bad_irq(unsigned int irq)
{
- smtc_im_ack_irq(irq);
printk("unexpected IRQ # %d\n", irq);
}
@@ -142,23 +141,7 @@ void __irq_entry do_IRQ(unsigned int irq)
{
irq_enter();
check_stack_overflow();
- if (!smtc_handle_on_other_cpu(irq))
- generic_handle_irq(irq);
- irq_exit();
-}
-
-#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-/*
- * To avoid inefficient and in some cases pathological re-checking of
- * IRQ affinity, we have this variant that skips the affinity check.
- */
-
-void __irq_entry do_IRQ_no_affinity(unsigned int irq)
-{
- irq_enter();
- smtc_im_backstop(irq);
generic_handle_irq(irq);
irq_exit();
}
-#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 72ef2d25cbf..e498f2b3646 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -150,7 +150,7 @@ int __init mips_cpu_intc_init(struct device_node *of_node,
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\n");
+ panic("Failed to add irqdomain for MIPS CPU");
return 0;
}
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index fcaac2f132f..7afcc2f22c0 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -32,6 +32,7 @@
#include <asm/cacheflush.h>
#include <asm/processor.h>
#include <asm/sigcontext.h>
+#include <asm/uaccess.h>
static struct hard_trap_info {
unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */
@@ -208,7 +209,14 @@ void arch_kgdb_breakpoint(void)
static void kgdb_call_nmi_hook(void *ignored)
{
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+
kgdb_nmicallback(raw_smp_processor_id(), NULL);
+
+ set_fs(old_fs);
}
void kgdb_roundup_cpus(unsigned long flags)
@@ -282,6 +290,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
struct die_args *args = (struct die_args *)ptr;
struct pt_regs *regs = args->regs;
int trap = (regs->cp0_cause & 0x7c) >> 2;
+ mm_segment_t old_fs;
#ifdef CONFIG_KPROBES
/*
@@ -296,11 +305,17 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
if (user_mode(regs))
return NOTIFY_DONE;
+ /* Kernel mode. Set correct address limit */
+ old_fs = get_fs();
+ set_fs(get_ds());
+
if (atomic_read(&kgdb_active) != -1)
kgdb_nmicallback(smp_processor_id(), regs);
- if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs))
+ if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) {
+ set_fs(old_fs);
return NOTIFY_DONE;
+ }
if (atomic_read(&kgdb_setting_breakpoint))
if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst))
@@ -310,6 +325,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
local_irq_enable();
__flush_cache_all();
+ set_fs(old_fs);
return NOTIFY_STOP;
}
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
new file mode 100644
index 00000000000..f76f7a08412
--- /dev/null
+++ b/arch/mips/kernel/mips-cm.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 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/errno.h>
+
+#include <asm/mips-cm.h>
+#include <asm/mipsregs.h>
+
+void __iomem *mips_cm_base;
+void __iomem *mips_cm_l2sync_base;
+
+phys_t __mips_cm_phys_base(void)
+{
+ u32 config3 = read_c0_config3();
+ u32 cmgcr;
+
+ /* Check the CMGCRBase register is implemented */
+ if (!(config3 & MIPS_CONF3_CMGCR))
+ return 0;
+
+ /* Read the address from CMGCRBase */
+ cmgcr = read_c0_cmgcrbase();
+ return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32);
+}
+
+phys_t mips_cm_phys_base(void)
+ __attribute__((weak, alias("__mips_cm_phys_base")));
+
+phys_t __mips_cm_l2sync_phys_base(void)
+{
+ u32 base_reg;
+
+ /*
+ * If the L2-only sync region is already enabled then leave it at it's
+ * current location.
+ */
+ base_reg = read_gcr_l2_only_sync_base();
+ if (base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK)
+ return base_reg & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK;
+
+ /* Default to following the CM */
+ return mips_cm_phys_base() + MIPS_CM_GCR_SIZE;
+}
+
+phys_t mips_cm_l2sync_phys_base(void)
+ __attribute__((weak, alias("__mips_cm_l2sync_phys_base")));
+
+static void mips_cm_probe_l2sync(void)
+{
+ unsigned major_rev;
+ phys_t addr;
+
+ /* L2-only sync was introduced with CM major revision 6 */
+ major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >>
+ CM_GCR_REV_MAJOR_SHF;
+ if (major_rev < 6)
+ return;
+
+ /* Find a location for the L2 sync region */
+ addr = mips_cm_l2sync_phys_base();
+ BUG_ON((addr & CM_GCR_L2_ONLY_SYNC_BASE_SYNCBASE_MSK) != addr);
+ if (!addr)
+ return;
+
+ /* Set the region base address & enable it */
+ write_gcr_l2_only_sync_base(addr | CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN_MSK);
+
+ /* Map the region */
+ mips_cm_l2sync_base = ioremap_nocache(addr, MIPS_CM_L2SYNC_SIZE);
+}
+
+int mips_cm_probe(void)
+{
+ phys_t addr;
+ u32 base_reg;
+
+ addr = mips_cm_phys_base();
+ BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr);
+ if (!addr)
+ return -ENODEV;
+
+ mips_cm_base = ioremap_nocache(addr, MIPS_CM_GCR_SIZE);
+ if (!mips_cm_base)
+ return -ENXIO;
+
+ /* sanity check that we're looking at a CM */
+ base_reg = read_gcr_base();
+ if ((base_reg & CM_GCR_BASE_GCRBASE_MSK) != addr) {
+ pr_err("GCRs appear to have been moved (expected them at 0x%08lx)!\n",
+ (unsigned long)addr);
+ mips_cm_base = NULL;
+ return -ENODEV;
+ }
+
+ /* set default target to memory */
+ base_reg &= ~CM_GCR_BASE_CMDEFTGT_MSK;
+ base_reg |= CM_GCR_BASE_CMDEFTGT_MEM;
+ write_gcr_base(base_reg);
+
+ /* disable CM regions */
+ write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+ write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+ write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+ write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+ write_gcr_reg2_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+ write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+ write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
+ write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+
+ /* probe for an L2-only sync region */
+ mips_cm_probe_l2sync();
+
+ return 0;
+}
diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c
new file mode 100644
index 00000000000..ba473608a34
--- /dev/null
+++ b/arch/mips/kernel/mips-cpc.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2013 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/errno.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
+
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
+
+void __iomem *mips_cpc_base;
+
+static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock);
+
+static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags);
+
+phys_t __weak mips_cpc_phys_base(void)
+{
+ u32 cpc_base;
+
+ if (!mips_cm_present())
+ return 0;
+
+ if (!(read_gcr_cpc_status() & CM_GCR_CPC_STATUS_EX_MSK))
+ return 0;
+
+ /* If the CPC is already enabled, leave it so */
+ cpc_base = read_gcr_cpc_base();
+ if (cpc_base & CM_GCR_CPC_BASE_CPCEN_MSK)
+ return cpc_base & CM_GCR_CPC_BASE_CPCBASE_MSK;
+
+ /* Otherwise, give it the default address & enable it */
+ cpc_base = mips_cpc_default_phys_base();
+ write_gcr_cpc_base(cpc_base | CM_GCR_CPC_BASE_CPCEN_MSK);
+ return cpc_base;
+}
+
+int mips_cpc_probe(void)
+{
+ phys_t addr;
+ unsigned cpu;
+
+ for_each_possible_cpu(cpu)
+ spin_lock_init(&per_cpu(cpc_core_lock, cpu));
+
+ addr = mips_cpc_phys_base();
+ if (!addr)
+ return -ENODEV;
+
+ mips_cpc_base = ioremap_nocache(addr, 0x8000);
+ if (!mips_cpc_base)
+ return -ENXIO;
+
+ return 0;
+}
+
+void mips_cpc_lock_other(unsigned int core)
+{
+ unsigned curr_core;
+ preempt_disable();
+ curr_core = current_cpu_data.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);
+}
+
+void mips_cpc_unlock_other(void)
+{
+ unsigned curr_core = current_cpu_data.core;
+ spin_unlock_irqrestore(&per_cpu(cpc_core_lock, curr_core),
+ per_cpu(cpc_core_lock_flags, curr_core));
+ preempt_enable();
+}
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index cb098628aee..362bb3707e6 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -1,5 +1,5 @@
/*
- * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * General MIPS MT support routines, usable in AP/SP and SMVP.
* Copyright (C) 2005 Mips Technologies, Inc
*/
#include <linux/cpu.h>
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index 6ded9bd1489..88b1ef5f868 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -1,5 +1,5 @@
/*
- * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * General MIPS MT support routines, usable in AP/SP and SMVP.
* Copyright (C) 2005 Mips Technologies, Inc
*/
@@ -57,9 +57,6 @@ void mips_mt_regdump(unsigned long mvpctl)
int tc;
unsigned long haltval;
unsigned long tcstatval;
-#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_soft_dump(void);
-#endif /* CONFIG_MIPT_MT_SMTC */
local_irq_save(flags);
vpflags = dvpe();
@@ -116,9 +113,6 @@ void mips_mt_regdump(unsigned long mvpctl)
if (!haltval)
write_tc_c0_tchalt(0);
}
-#ifdef CONFIG_MIPS_MT_SMTC
- smtc_soft_dump();
-#endif /* CONFIG_MIPT_MT_SMTC */
printk("===========================\n");
evpe(vpflags);
local_irq_restore(flags);
@@ -295,21 +289,11 @@ void mips_mt_set_cpuoptions(void)
void mt_cflush_lockdown(void)
{
-#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_cflush_lockdown(void);
-
- smtc_cflush_lockdown();
-#endif /* CONFIG_MIPS_MT_SMTC */
/* FILL IN VSMP and AP/SP VERSIONS HERE */
}
void mt_cflush_release(void)
{
-#ifdef CONFIG_MIPS_MT_SMTC
- void smtc_cflush_release(void);
-
- smtc_cflush_release();
-#endif /* CONFIG_MIPS_MT_SMTC */
/* FILL IN VSMP and AP/SP VERSIONS HERE */
}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 6e58e97fcd3..2607c3a4ff7 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -16,12 +16,20 @@
#include <asm/ftrace.h>
extern void *__bzero(void *__s, size_t __count);
+extern long __strncpy_from_kernel_nocheck_asm(char *__to,
+ const char *__from, long __len);
+extern long __strncpy_from_kernel_asm(char *__to, const char *__from,
+ long __len);
extern long __strncpy_from_user_nocheck_asm(char *__to,
const char *__from, long __len);
extern long __strncpy_from_user_asm(char *__to, const char *__from,
long __len);
+extern long __strlen_kernel_nocheck_asm(const char *s);
+extern long __strlen_kernel_asm(const char *s);
extern long __strlen_user_nocheck_asm(const char *s);
extern long __strlen_user_asm(const char *s);
+extern long __strnlen_kernel_nocheck_asm(const char *s);
+extern long __strnlen_kernel_asm(const char *s);
extern long __strnlen_user_nocheck_asm(const char *s);
extern long __strnlen_user_asm(const char *s);
@@ -43,17 +51,31 @@ EXPORT_SYMBOL(copy_page);
*/
EXPORT_SYMBOL(__copy_user);
EXPORT_SYMBOL(__copy_user_inatomic);
+#ifdef CONFIG_EVA
+EXPORT_SYMBOL(__copy_from_user_eva);
+EXPORT_SYMBOL(__copy_in_user_eva);
+EXPORT_SYMBOL(__copy_to_user_eva);
+EXPORT_SYMBOL(__copy_user_inatomic_eva);
+#endif
EXPORT_SYMBOL(__bzero);
+EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
+EXPORT_SYMBOL(__strncpy_from_kernel_asm);
EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
EXPORT_SYMBOL(__strncpy_from_user_asm);
+EXPORT_SYMBOL(__strlen_kernel_nocheck_asm);
+EXPORT_SYMBOL(__strlen_kernel_asm);
EXPORT_SYMBOL(__strlen_user_nocheck_asm);
EXPORT_SYMBOL(__strlen_user_asm);
+EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm);
+EXPORT_SYMBOL(__strnlen_kernel_asm);
EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
EXPORT_SYMBOL(__strnlen_user_asm);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_nocheck);
-EXPORT_SYMBOL(__csum_partial_copy_user);
+EXPORT_SYMBOL(__csum_partial_copy_kernel);
+EXPORT_SYMBOL(__csum_partial_copy_to_user);
+EXPORT_SYMBOL(__csum_partial_copy_from_user);
EXPORT_SYMBOL(invalid_pte_table);
#ifdef CONFIG_FUNCTION_TRACER
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 977a623d925..2a52568dbcd 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -23,6 +23,7 @@
#include <linux/moduleloader.h>
#include <linux/elf.h>
#include <linux/mm.h>
+#include <linux/numa.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/fs.h>
@@ -46,7 +47,7 @@ static DEFINE_SPINLOCK(dbe_lock);
void *module_alloc(unsigned long size)
{
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
- GFP_KERNEL, PAGE_KERNEL, -1,
+ GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
__builtin_return_address(0));
}
#endif
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index 4204d76af85..f6547680c81 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -10,24 +10,12 @@
* Copyright (C) 2000 MIPS Technologies, Inc.
* written by Carsten Langgaard, carstenl@mips.com
*/
-#include <asm/asm.h>
-#include <asm/cachectl.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsregs.h>
-#include <asm/asm-offsets.h>
-#include <asm/pgtable-bits.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/thread_info.h>
-
-#include <asm/asmmacro.h>
-
-/*
- * Offset to the current process status flags, the first 32 bytes of the
- * stack are not used.
- */
-#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
+#define USE_ALTERNATE_RESUME_IMPL 1
+ .set push
+ .set arch=mips64r2
+#include "r4k_switch.S"
+ .set pop
/*
* task_struct *resume(task_struct *prev, task_struct *next,
* struct thread_info *next_ti, int usedfpu)
@@ -40,6 +28,61 @@
cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(a0)
+ /*
+ * check if we need to save FPU registers
+ */
+ PTR_L t3, TASK_THREAD_INFO(a0)
+ LONG_L t0, TI_FLAGS(t3)
+ li t1, _TIF_USEDFPU
+ and t2, t0, t1
+ beqz t2, 1f
+ nor t1, zero, t1
+
+ and t0, t0, t1
+ LONG_S t0, TI_FLAGS(t3)
+
+ /*
+ * 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:
+
+ /* check if we need to save COP2 registers */
+ PTR_L t2, TASK_THREAD_INFO(a0)
+ LONG_L t0, ST_OFF(t2)
+ bbit0 t0, 30, 1f
+
+ /* Disable COP2 in the stored process state */
+ li t1, ST0_CU2
+ xor t0, t1
+ LONG_S t0, ST_OFF(t2)
+
+ /* Enable COP2 so we can save it */
+ mfc0 t0, CP0_STATUS
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+
+ /* Save COP2 */
+ daddu a0, THREAD_CP2
+ jal octeon_cop2_save
+ dsubu a0, THREAD_CP2
+
+ /* Disable COP2 now that we are done */
+ mfc0 t0, CP0_STATUS
+ li t1, ST0_CU2
+ xor t0, t1
+ mtc0 t0, CP0_STATUS
+
+1:
#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
/* Check if we need to store CVMSEG state */
mfc0 t0, $11,7 /* CvmMemCtl */
@@ -73,7 +116,7 @@
3:
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
- PTR_L t8, __stack_chk_guard
+ PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
LONG_S t9, 0(t8)
#endif
@@ -85,12 +128,7 @@
move $28, a2
cpu_restore_nonscratch a1
-#if (_THREAD_SIZE - 32) < 0x8000
- PTR_ADDIU t0, $28, _THREAD_SIZE - 32
-#else
- PTR_LI t0, _THREAD_SIZE - 32
- PTR_ADDU t0, $28
-#endif
+ PTR_ADDU t0, $28, _THREAD_SIZE - 32
set_saved_sp t0, t1, t2
mfc0 t1, CP0_STATUS /* Do we really need this? */
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 45f1ffcf1a4..4f2d9dece7a 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -805,7 +805,7 @@ static void reset_counters(void *arg)
}
}
-/* 24K/34K/1004K cores can share the same event map. */
+/* 24K/34K/1004K/interAptiv/loongson1 cores share the same event map. */
static const struct mips_perf_event mipsxxcore_event_map
[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD, P },
@@ -814,8 +814,8 @@ static const struct mips_perf_event mipsxxcore_event_map
[PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
};
-/* 74K core has different branch event code. */
-static const struct mips_perf_event mipsxx74Kcore_event_map
+/* 74K/proAptiv core has different branch event code. */
+static const struct mips_perf_event mipsxxcore_event_map2
[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD, P },
[PERF_COUNT_HW_INSTRUCTIONS] = { 0x01, CNTR_EVEN | CNTR_ODD, T },
@@ -849,7 +849,7 @@ static const struct mips_perf_event xlp_event_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BRANCH_MISSES] = { 0x1c, CNTR_ALL }, /* PAPI_BR_MSP */
};
-/* 24K/34K/1004K cores can share the same cache event map. */
+/* 24K/34K/1004K/interAptiv/loongson1 cores share the same cache event map. */
static const struct mips_perf_event mipsxxcore_cache_map
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -930,8 +930,8 @@ static const struct mips_perf_event mipsxxcore_cache_map
},
};
-/* 74K core has completely different cache event map. */
-static const struct mips_perf_event mipsxx74Kcore_cache_map
+/* 74K/proAptiv core has completely different cache event map. */
+static const struct mips_perf_event mipsxxcore_cache_map2
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
@@ -971,13 +971,18 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
[C(LL)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x1c, CNTR_ODD, P },
- [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN | CNTR_ODD, P },
+ [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN, P },
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { 0x1c, CNTR_ODD, P },
- [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN | CNTR_ODD, P },
+ [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN, P },
},
},
+/*
+ * 74K core does not have specific DTLB events. proAptiv core has
+ * "speculative" DTLB events which are numbered 0x63 (even/odd) and
+ * not included here. One can use raw events if really needed.
+ */
[C(ITLB)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x04, CNTR_EVEN, T },
@@ -1378,6 +1383,10 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
#define IS_BOTH_COUNTERS_74K_EVENT(b) \
((b) == 0 || (b) == 1)
+/* proAptiv */
+#define IS_BOTH_COUNTERS_PROAPTIV_EVENT(b) \
+ ((b) == 0 || (b) == 1)
+
/* 1004K */
#define IS_BOTH_COUNTERS_1004K_EVENT(b) \
((b) == 0 || (b) == 1 || (b) == 11)
@@ -1391,6 +1400,20 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
#define IS_RANGE_V_1004K_EVENT(r) ((r) == 47)
#endif
+/* interAptiv */
+#define IS_BOTH_COUNTERS_INTERAPTIV_EVENT(b) \
+ ((b) == 0 || (b) == 1 || (b) == 11)
+#ifdef CONFIG_MIPS_MT_SMP
+/* The P/V/T info is not provided for "(b) == 38" in SUM, assume P. */
+#define IS_RANGE_P_INTERAPTIV_EVENT(r, b) \
+ ((b) == 0 || (r) == 18 || (b) == 21 || (b) == 22 || \
+ (b) == 25 || (b) == 36 || (b) == 38 || (b) == 39 || \
+ (r) == 44 || (r) == 174 || (r) == 176 || ((b) >= 50 && \
+ (b) <= 59) || (r) == 188 || (b) == 61 || (b) == 62 || \
+ ((b) >= 64 && (b) <= 67))
+#define IS_RANGE_V_INTERAPTIV_EVENT(r) ((r) == 47 || (r) == 175)
+#endif
+
/* BMIPS5000 */
#define IS_BOTH_COUNTERS_BMIPS5000_EVENT(b) \
((b) == 0 || (b) == 1)
@@ -1442,6 +1465,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
#endif
break;
case CPU_74K:
+ case CPU_1074K:
if (IS_BOTH_COUNTERS_74K_EVENT(base_id))
raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
else
@@ -1451,6 +1475,16 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
raw_event.range = P;
#endif
break;
+ case CPU_PROAPTIV:
+ if (IS_BOTH_COUNTERS_PROAPTIV_EVENT(base_id))
+ raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+ else
+ raw_event.cntr_mask =
+ raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+ raw_event.range = P;
+#endif
+ break;
case CPU_1004K:
if (IS_BOTH_COUNTERS_1004K_EVENT(base_id))
raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
@@ -1466,6 +1500,21 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
raw_event.range = T;
#endif
break;
+ case CPU_INTERAPTIV:
+ if (IS_BOTH_COUNTERS_INTERAPTIV_EVENT(base_id))
+ raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+ else
+ raw_event.cntr_mask =
+ raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+ if (IS_RANGE_P_INTERAPTIV_EVENT(raw_id, base_id))
+ raw_event.range = P;
+ else if (unlikely(IS_RANGE_V_INTERAPTIV_EVENT(raw_id)))
+ raw_event.range = V;
+ else
+ raw_event.range = T;
+#endif
+ break;
case CPU_BMIPS5000:
if (IS_BOTH_COUNTERS_BMIPS5000_EVENT(base_id))
raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
@@ -1576,14 +1625,29 @@ init_hw_perf_events(void)
break;
case CPU_74K:
mipspmu.name = "mips/74K";
- mipspmu.general_event_map = &mipsxx74Kcore_event_map;
- mipspmu.cache_event_map = &mipsxx74Kcore_cache_map;
+ mipspmu.general_event_map = &mipsxxcore_event_map2;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+ break;
+ case CPU_PROAPTIV:
+ mipspmu.name = "mips/proAptiv";
+ 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;
mipspmu.cache_event_map = &mipsxxcore_cache_map;
break;
+ case CPU_1074K:
+ mipspmu.name = "mips/1074K";
+ mipspmu.general_event_map = &mipsxxcore_event_map;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map;
+ break;
+ case CPU_INTERAPTIV:
+ mipspmu.name = "mips/interAptiv";
+ mipspmu.general_event_map = &mipsxxcore_event_map;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map;
+ break;
case CPU_LOONGSON1:
mipspmu.name = "mips/loongson1";
mipspmu.general_event_map = &mipsxxcore_event_map;
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
new file mode 100644
index 00000000000..c4c2069d3a2
--- /dev/null
+++ b/arch/mips/kernel/pm-cps.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/cacheflush.h>
+#include <asm/cacheops.h>
+#include <asm/idle.h>
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
+#include <asm/mipsmtregs.h>
+#include <asm/pm.h>
+#include <asm/pm-cps.h>
+#include <asm/smp-cps.h>
+#include <asm/uasm.h>
+
+/*
+ * cps_nc_entry_fn - type of a generated non-coherent state entry function
+ * @online: the count of online coupled VPEs
+ * @nc_ready_count: pointer to a non-coherent mapping of the core ready_count
+ *
+ * The code entering & exiting non-coherent states is generated at runtime
+ * using uasm, in order to ensure that the compiler cannot insert a stray
+ * memory access at an unfortunate time and to allow the generation of optimal
+ * core-specific code particularly for cache routines. If coupled_coherence
+ * is non-zero and this is the entry function for the CPS_PM_NC_WAIT state,
+ * returns the number of VPEs that were in the wait state at the point this
+ * VPE left it. Returns garbage if coupled_coherence is zero or this is not
+ * the entry function for CPS_PM_NC_WAIT.
+ */
+typedef unsigned (*cps_nc_entry_fn)(unsigned online, u32 *nc_ready_count);
+
+/*
+ * The entry point of the generated non-coherent idle state entry/exit
+ * functions. Actually per-core rather than per-CPU.
+ */
+static DEFINE_PER_CPU_READ_MOSTLY(cps_nc_entry_fn[CPS_PM_STATE_COUNT],
+ nc_asm_enter);
+
+/* Bitmap indicating which states are supported by the system */
+DECLARE_BITMAP(state_support, CPS_PM_STATE_COUNT);
+
+/*
+ * Indicates the number of coupled VPEs ready to operate in a non-coherent
+ * state. Actually per-core rather than per-CPU.
+ */
+static DEFINE_PER_CPU_ALIGNED(u32*, ready_count);
+static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc);
+
+/* Indicates online CPUs coupled with the current CPU */
+static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled);
+
+/*
+ * Used to synchronize entry to deep idle states. Actually per-core rather
+ * than per-CPU.
+ */
+static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier);
+
+/* Saved CPU state across the CPS_PM_POWER_GATED state */
+DEFINE_PER_CPU_ALIGNED(struct mips_static_suspend_state, cps_cpu_state);
+
+/* A somewhat arbitrary number of labels & relocs for uasm */
+static struct uasm_label labels[32] __initdata;
+static struct uasm_reloc relocs[32] __initdata;
+
+/* CPU dependant sync types */
+static unsigned stype_intervention;
+static unsigned stype_memory;
+static unsigned stype_ordering;
+
+enum mips_reg {
+ zero, at, v0, v1, a0, a1, a2, a3,
+ t0, t1, t2, t3, t4, t5, t6, t7,
+ s0, s1, s2, s3, s4, s5, s6, s7,
+ t8, t9, k0, k1, gp, sp, fp, ra,
+};
+
+bool cps_pm_support_state(enum cps_pm_state state)
+{
+ return test_bit(state, state_support);
+}
+
+static void coupled_barrier(atomic_t *a, unsigned online)
+{
+ /*
+ * This function is effectively the same as
+ * cpuidle_coupled_parallel_barrier, which can't be used here since
+ * there's no cpuidle device.
+ */
+
+ if (!coupled_coherence)
+ return;
+
+ smp_mb__before_atomic();
+ atomic_inc(a);
+
+ while (atomic_read(a) < online)
+ cpu_relax();
+
+ if (atomic_inc_return(a) == online * 2) {
+ atomic_set(a, 0);
+ return;
+ }
+
+ while (atomic_read(a) > online)
+ cpu_relax();
+}
+
+int cps_pm_enter_state(enum cps_pm_state state)
+{
+ unsigned cpu = smp_processor_id();
+ unsigned core = current_cpu_data.core;
+ unsigned online, left;
+ cpumask_t *coupled_mask = this_cpu_ptr(&online_coupled);
+ u32 *core_ready_count, *nc_core_ready_count;
+ void *nc_addr;
+ cps_nc_entry_fn entry;
+ struct core_boot_config *core_cfg;
+ struct vpe_boot_config *vpe_cfg;
+
+ /* Check that there is an entry function for this state */
+ entry = per_cpu(nc_asm_enter, core)[state];
+ if (!entry)
+ return -EINVAL;
+
+ /* Calculate which coupled CPUs (VPEs) are online */
+#ifdef CONFIG_MIPS_MT
+ if (cpu_online(cpu)) {
+ cpumask_and(coupled_mask, cpu_online_mask,
+ &cpu_sibling_map[cpu]);
+ online = cpumask_weight(coupled_mask);
+ cpumask_clear_cpu(cpu, coupled_mask);
+ } else
+#endif
+ {
+ cpumask_clear(coupled_mask);
+ online = 1;
+ }
+
+ /* Setup the VPE to run mips_cps_pm_restore when started again */
+ if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+ core_cfg = &mips_cps_core_bootcfg[core];
+ vpe_cfg = &core_cfg->vpe_config[current_cpu_data.vpe_id];
+ vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
+ vpe_cfg->gp = (unsigned long)current_thread_info();
+ vpe_cfg->sp = 0;
+ }
+
+ /* Indicate that this CPU might not be coherent */
+ cpumask_clear_cpu(cpu, &cpu_coherent_mask);
+ smp_mb__after_atomic();
+
+ /* Create a non-coherent mapping of the core ready_count */
+ core_ready_count = per_cpu(ready_count, core);
+ nc_addr = kmap_noncoherent(virt_to_page(core_ready_count),
+ (unsigned long)core_ready_count);
+ nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK);
+ nc_core_ready_count = nc_addr;
+
+ /* Ensure ready_count is zero-initialised before the assembly runs */
+ ACCESS_ONCE(*nc_core_ready_count) = 0;
+ coupled_barrier(&per_cpu(pm_barrier, core), online);
+
+ /* Run the generated entry code */
+ left = entry(online, nc_core_ready_count);
+
+ /* Remove the non-coherent mapping of ready_count */
+ kunmap_noncoherent();
+
+ /* Indicate that this CPU is definitely coherent */
+ cpumask_set_cpu(cpu, &cpu_coherent_mask);
+
+ /*
+ * If this VPE is the first to leave the non-coherent wait state then
+ * it needs to wake up any coupled VPEs still running their wait
+ * instruction so that they return to cpuidle, which can then complete
+ * coordination between the coupled VPEs & provide the governor with
+ * a chance to reflect on the length of time the VPEs were in the
+ * idle state.
+ */
+ if (coupled_coherence && (state == CPS_PM_NC_WAIT) && (left == online))
+ arch_send_call_function_ipi_mask(coupled_mask);
+
+ return 0;
+}
+
+static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl,
+ struct uasm_reloc **pr,
+ const struct cache_desc *cache,
+ unsigned op, int lbl)
+{
+ unsigned cache_size = cache->ways << cache->waybit;
+ unsigned i;
+ const unsigned unroll_lines = 32;
+
+ /* If the cache isn't present this function has it easy */
+ if (cache->flags & MIPS_CACHE_NOT_PRESENT)
+ return;
+
+ /* Load base address */
+ UASM_i_LA(pp, t0, (long)CKSEG0);
+
+ /* Calculate end address */
+ if (cache_size < 0x8000)
+ uasm_i_addiu(pp, t1, t0, cache_size);
+ else
+ UASM_i_LA(pp, t1, (long)(CKSEG0 + cache_size));
+
+ /* Start of cache op loop */
+ uasm_build_label(pl, *pp, lbl);
+
+ /* Generate the cache ops */
+ for (i = 0; i < unroll_lines; i++)
+ uasm_i_cache(pp, op, i * cache->linesz, t0);
+
+ /* Update the base address */
+ uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz);
+
+ /* Loop if we haven't reached the end address yet */
+ uasm_il_bne(pp, pr, t0, t1, lbl);
+ uasm_i_nop(pp);
+}
+
+static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
+ struct uasm_reloc **pr,
+ const struct cpuinfo_mips *cpu_info,
+ int lbl)
+{
+ unsigned i, fsb_size = 8;
+ unsigned num_loads = (fsb_size * 3) / 2;
+ unsigned line_stride = 2;
+ unsigned line_size = cpu_info->dcache.linesz;
+ unsigned perf_counter, perf_event;
+ unsigned revision = cpu_info->processor_id & PRID_REV_MASK;
+
+ /*
+ * Determine whether this CPU requires an FSB flush, and if so which
+ * performance counter/event reflect stalls due to a full FSB.
+ */
+ switch (__get_cpu_type(cpu_info->cputype)) {
+ case CPU_INTERAPTIV:
+ perf_counter = 1;
+ perf_event = 51;
+ break;
+
+ case CPU_PROAPTIV:
+ /* Newer proAptiv cores don't require this workaround */
+ if (revision >= PRID_REV_ENCODE_332(1, 1, 0))
+ return 0;
+
+ /* On older ones it's unavailable */
+ return -1;
+
+ /* CPUs which do not require the workaround */
+ case CPU_P5600:
+ return 0;
+
+ default:
+ WARN_ONCE(1, "pm-cps: FSB flush unsupported for this CPU\n");
+ return -1;
+ }
+
+ /*
+ * Ensure that the fill/store buffer (FSB) is not holding the results
+ * of a prefetch, since if it is then the CPC sequencer may become
+ * stuck in the D3 (ClrBus) state whilst entering a low power state.
+ */
+
+ /* Preserve perf counter setup */
+ uasm_i_mfc0(pp, t2, 25, (perf_counter * 2) + 0); /* PerfCtlN */
+ uasm_i_mfc0(pp, t3, 25, (perf_counter * 2) + 1); /* PerfCntN */
+
+ /* Setup perf counter to count FSB full pipeline stalls */
+ uasm_i_addiu(pp, t0, zero, (perf_event << 5) | 0xf);
+ uasm_i_mtc0(pp, t0, 25, (perf_counter * 2) + 0); /* PerfCtlN */
+ uasm_i_ehb(pp);
+ uasm_i_mtc0(pp, zero, 25, (perf_counter * 2) + 1); /* PerfCntN */
+ uasm_i_ehb(pp);
+
+ /* Base address for loads */
+ UASM_i_LA(pp, t0, (long)CKSEG0);
+
+ /* Start of clear loop */
+ uasm_build_label(pl, *pp, lbl);
+
+ /* Perform some loads to fill the FSB */
+ for (i = 0; i < num_loads; i++)
+ uasm_i_lw(pp, zero, i * line_size * line_stride, t0);
+
+ /*
+ * Invalidate the new D-cache entries so that the cache will need
+ * refilling (via the FSB) if the loop is executed again.
+ */
+ for (i = 0; i < num_loads; i++) {
+ uasm_i_cache(pp, Hit_Invalidate_D,
+ i * line_size * line_stride, t0);
+ uasm_i_cache(pp, Hit_Writeback_Inv_SD,
+ i * line_size * line_stride, t0);
+ }
+
+ /* Completion barrier */
+ uasm_i_sync(pp, stype_memory);
+ uasm_i_ehb(pp);
+
+ /* Check whether the pipeline stalled due to the FSB being full */
+ uasm_i_mfc0(pp, t1, 25, (perf_counter * 2) + 1); /* PerfCntN */
+
+ /* Loop if it didn't */
+ uasm_il_beqz(pp, pr, t1, lbl);
+ uasm_i_nop(pp);
+
+ /* Restore perf counter 1. The count may well now be wrong... */
+ uasm_i_mtc0(pp, t2, 25, (perf_counter * 2) + 0); /* PerfCtlN */
+ uasm_i_ehb(pp);
+ uasm_i_mtc0(pp, t3, 25, (perf_counter * 2) + 1); /* PerfCntN */
+ uasm_i_ehb(pp);
+
+ return 0;
+}
+
+static void __init cps_gen_set_top_bit(u32 **pp, struct uasm_label **pl,
+ struct uasm_reloc **pr,
+ unsigned r_addr, int lbl)
+{
+ uasm_i_lui(pp, t0, uasm_rel_hi(0x80000000));
+ uasm_build_label(pl, *pp, lbl);
+ uasm_i_ll(pp, t1, 0, r_addr);
+ uasm_i_or(pp, t1, t1, t0);
+ uasm_i_sc(pp, t1, 0, r_addr);
+ uasm_il_beqz(pp, pr, t1, lbl);
+ uasm_i_nop(pp);
+}
+
+static void * __init cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
+{
+ struct uasm_label *l = labels;
+ struct uasm_reloc *r = relocs;
+ u32 *buf, *p;
+ const unsigned r_online = a0;
+ const unsigned r_nc_count = a1;
+ const unsigned r_pcohctl = t7;
+ const unsigned max_instrs = 256;
+ unsigned cpc_cmd;
+ int err;
+ enum {
+ lbl_incready = 1,
+ lbl_poll_cont,
+ lbl_secondary_hang,
+ lbl_disable_coherence,
+ lbl_flush_fsb,
+ lbl_invicache,
+ lbl_flushdcache,
+ lbl_hang,
+ lbl_set_cont,
+ lbl_secondary_cont,
+ lbl_decready,
+ };
+
+ /* Allocate a buffer to hold the generated code */
+ p = buf = kcalloc(max_instrs, sizeof(u32), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ /* Clear labels & relocs ready for (re)use */
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+
+ if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+ /*
+ * Save CPU state. Note the non-standard calling convention
+ * with the return address placed in v0 to avoid clobbering
+ * the ra register before it is saved.
+ */
+ UASM_i_LA(&p, t0, (long)mips_cps_pm_save);
+ uasm_i_jalr(&p, v0, t0);
+ uasm_i_nop(&p);
+ }
+
+ /*
+ * Load addresses of required CM & CPC registers. This is done early
+ * because they're needed in both the enable & disable coherence steps
+ * but in the coupled case the enable step will only run on one VPE.
+ */
+ UASM_i_LA(&p, r_pcohctl, (long)addr_gcr_cl_coherence());
+
+ if (coupled_coherence) {
+ /* Increment ready_count */
+ uasm_i_sync(&p, stype_ordering);
+ uasm_build_label(&l, p, lbl_incready);
+ uasm_i_ll(&p, t1, 0, r_nc_count);
+ uasm_i_addiu(&p, t2, t1, 1);
+ uasm_i_sc(&p, t2, 0, r_nc_count);
+ uasm_il_beqz(&p, &r, t2, lbl_incready);
+ uasm_i_addiu(&p, t1, t1, 1);
+
+ /* Ordering barrier */
+ uasm_i_sync(&p, stype_ordering);
+
+ /*
+ * If this is the last VPE to become ready for non-coherence
+ * then it should branch below.
+ */
+ uasm_il_beq(&p, &r, t1, r_online, lbl_disable_coherence);
+ uasm_i_nop(&p);
+
+ if (state < CPS_PM_POWER_GATED) {
+ /*
+ * Otherwise this is not the last VPE to become ready
+ * for non-coherence. It needs to wait until coherence
+ * has been disabled before proceeding, which it will do
+ * by polling for the top bit of ready_count being set.
+ */
+ uasm_i_addiu(&p, t1, zero, -1);
+ uasm_build_label(&l, p, lbl_poll_cont);
+ uasm_i_lw(&p, t0, 0, r_nc_count);
+ uasm_il_bltz(&p, &r, t0, lbl_secondary_cont);
+ uasm_i_ehb(&p);
+ uasm_i_yield(&p, zero, t1);
+ uasm_il_b(&p, &r, lbl_poll_cont);
+ uasm_i_nop(&p);
+ } else {
+ /*
+ * The core will lose power & this VPE will not continue
+ * so it can simply halt here.
+ */
+ uasm_i_addiu(&p, t0, zero, TCHALT_H);
+ uasm_i_mtc0(&p, t0, 2, 4);
+ uasm_build_label(&l, p, lbl_secondary_hang);
+ uasm_il_b(&p, &r, lbl_secondary_hang);
+ uasm_i_nop(&p);
+ }
+ }
+
+ /*
+ * This is the point of no return - this VPE will now proceed to
+ * disable coherence. At this point we *must* be sure that no other
+ * VPE within the core will interfere with the L1 dcache.
+ */
+ uasm_build_label(&l, p, lbl_disable_coherence);
+
+ /* Invalidate the L1 icache */
+ cps_gen_cache_routine(&p, &l, &r, &cpu_data[cpu].icache,
+ Index_Invalidate_I, lbl_invicache);
+
+ /* Writeback & invalidate the L1 dcache */
+ cps_gen_cache_routine(&p, &l, &r, &cpu_data[cpu].dcache,
+ Index_Writeback_Inv_D, lbl_flushdcache);
+
+ /* Completion barrier */
+ uasm_i_sync(&p, stype_memory);
+ uasm_i_ehb(&p);
+
+ /*
+ * Disable all but self interventions. The load from COHCTL is defined
+ * by the interAptiv & proAptiv SUMs as ensuring that the operation
+ * resulting from the preceeding store is complete.
+ */
+ uasm_i_addiu(&p, t0, zero, 1 << cpu_data[cpu].core);
+ uasm_i_sw(&p, t0, 0, r_pcohctl);
+ uasm_i_lw(&p, t0, 0, r_pcohctl);
+
+ /* Sync to ensure previous interventions are complete */
+ uasm_i_sync(&p, stype_intervention);
+ uasm_i_ehb(&p);
+
+ /* Disable coherence */
+ uasm_i_sw(&p, zero, 0, r_pcohctl);
+ uasm_i_lw(&p, t0, 0, r_pcohctl);
+
+ if (state >= CPS_PM_CLOCK_GATED) {
+ err = cps_gen_flush_fsb(&p, &l, &r, &cpu_data[cpu],
+ lbl_flush_fsb);
+ if (err)
+ goto out_err;
+
+ /* Determine the CPC command to issue */
+ switch (state) {
+ case CPS_PM_CLOCK_GATED:
+ cpc_cmd = CPC_Cx_CMD_CLOCKOFF;
+ break;
+ case CPS_PM_POWER_GATED:
+ cpc_cmd = CPC_Cx_CMD_PWRDOWN;
+ break;
+ default:
+ BUG();
+ goto out_err;
+ }
+
+ /* Issue the CPC command */
+ UASM_i_LA(&p, t0, (long)addr_cpc_cl_cmd());
+ uasm_i_addiu(&p, t1, zero, cpc_cmd);
+ uasm_i_sw(&p, t1, 0, t0);
+
+ if (state == CPS_PM_POWER_GATED) {
+ /* If anything goes wrong just hang */
+ uasm_build_label(&l, p, lbl_hang);
+ uasm_il_b(&p, &r, lbl_hang);
+ uasm_i_nop(&p);
+
+ /*
+ * There's no point generating more code, the core is
+ * powered down & if powered back up will run from the
+ * reset vector not from here.
+ */
+ goto gen_done;
+ }
+
+ /* Completion barrier */
+ uasm_i_sync(&p, stype_memory);
+ uasm_i_ehb(&p);
+ }
+
+ if (state == CPS_PM_NC_WAIT) {
+ /*
+ * At this point it is safe for all VPEs to proceed with
+ * execution. This VPE will set the top bit of ready_count
+ * to indicate to the other VPEs that they may continue.
+ */
+ if (coupled_coherence)
+ cps_gen_set_top_bit(&p, &l, &r, r_nc_count,
+ lbl_set_cont);
+
+ /*
+ * VPEs which did not disable coherence will continue
+ * executing, after coherence has been disabled, from this
+ * point.
+ */
+ uasm_build_label(&l, p, lbl_secondary_cont);
+
+ /* Now perform our wait */
+ uasm_i_wait(&p, 0);
+ }
+
+ /*
+ * Re-enable coherence. Note that for CPS_PM_NC_WAIT all coupled VPEs
+ * will run this. The first will actually re-enable coherence & the
+ * rest will just be performing a rather unusual nop.
+ */
+ uasm_i_addiu(&p, t0, zero, CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK);
+ uasm_i_sw(&p, t0, 0, r_pcohctl);
+ uasm_i_lw(&p, t0, 0, r_pcohctl);
+
+ /* Completion barrier */
+ uasm_i_sync(&p, stype_memory);
+ uasm_i_ehb(&p);
+
+ if (coupled_coherence && (state == CPS_PM_NC_WAIT)) {
+ /* Decrement ready_count */
+ uasm_build_label(&l, p, lbl_decready);
+ uasm_i_sync(&p, stype_ordering);
+ uasm_i_ll(&p, t1, 0, r_nc_count);
+ uasm_i_addiu(&p, t2, t1, -1);
+ uasm_i_sc(&p, t2, 0, r_nc_count);
+ uasm_il_beqz(&p, &r, t2, lbl_decready);
+ uasm_i_andi(&p, v0, t1, (1 << fls(smp_num_siblings)) - 1);
+
+ /* Ordering barrier */
+ uasm_i_sync(&p, stype_ordering);
+ }
+
+ if (coupled_coherence && (state == CPS_PM_CLOCK_GATED)) {
+ /*
+ * At this point it is safe for all VPEs to proceed with
+ * execution. This VPE will set the top bit of ready_count
+ * to indicate to the other VPEs that they may continue.
+ */
+ cps_gen_set_top_bit(&p, &l, &r, r_nc_count, lbl_set_cont);
+
+ /*
+ * This core will be reliant upon another core sending a
+ * power-up command to the CPC in order to resume operation.
+ * Thus an arbitrary VPE can't trigger the core leaving the
+ * idle state and the one that disables coherence might as well
+ * be the one to re-enable it. The rest will continue from here
+ * after that has been done.
+ */
+ uasm_build_label(&l, p, lbl_secondary_cont);
+
+ /* Ordering barrier */
+ uasm_i_sync(&p, stype_ordering);
+ }
+
+ /* The core is coherent, time to return to C code */
+ uasm_i_jr(&p, ra);
+ uasm_i_nop(&p);
+
+gen_done:
+ /* Ensure the code didn't exceed the resources allocated for it */
+ BUG_ON((p - buf) > max_instrs);
+ BUG_ON((l - labels) > ARRAY_SIZE(labels));
+ BUG_ON((r - relocs) > ARRAY_SIZE(relocs));
+
+ /* Patch branch offsets */
+ uasm_resolve_relocs(relocs, labels);
+
+ /* Flush the icache */
+ local_flush_icache_range((unsigned long)buf, (unsigned long)p);
+
+ return buf;
+out_err:
+ kfree(buf);
+ return NULL;
+}
+
+static int __init cps_gen_core_entries(unsigned cpu)
+{
+ enum cps_pm_state state;
+ unsigned core = cpu_data[cpu].core;
+ unsigned dlinesz = cpu_data[cpu].dcache.linesz;
+ void *entry_fn, *core_rc;
+
+ for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
+ if (per_cpu(nc_asm_enter, core)[state])
+ continue;
+ if (!test_bit(state, state_support))
+ continue;
+
+ entry_fn = cps_gen_entry_code(cpu, state);
+ if (!entry_fn) {
+ pr_err("Failed to generate core %u state %u entry\n",
+ core, state);
+ clear_bit(state, state_support);
+ }
+
+ per_cpu(nc_asm_enter, core)[state] = entry_fn;
+ }
+
+ if (!per_cpu(ready_count, core)) {
+ core_rc = kmalloc(dlinesz * 2, GFP_KERNEL);
+ if (!core_rc) {
+ pr_err("Failed allocate core %u ready_count\n", core);
+ return -ENOMEM;
+ }
+ per_cpu(ready_count_alloc, core) = core_rc;
+
+ /* Ensure ready_count is aligned to a cacheline boundary */
+ core_rc += dlinesz - 1;
+ core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1));
+ per_cpu(ready_count, core) = core_rc;
+ }
+
+ return 0;
+}
+
+static int __init cps_pm_init(void)
+{
+ unsigned cpu;
+ int err;
+
+ /* Detect appropriate sync types for the system */
+ switch (current_cpu_data.cputype) {
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ case CPU_M5150:
+ case CPU_P5600:
+ stype_intervention = 0x2;
+ stype_memory = 0x3;
+ stype_ordering = 0x10;
+ break;
+
+ default:
+ pr_warn("Power management is using heavyweight sync 0\n");
+ }
+
+ /* A CM is required for all non-coherent states */
+ if (!mips_cm_present()) {
+ pr_warn("pm-cps: no CM, non-coherent states unavailable\n");
+ goto out;
+ }
+
+ /*
+ * If interrupts were enabled whilst running a wait instruction on a
+ * non-coherent core then the VPE may end up processing interrupts
+ * whilst non-coherent. That would be bad.
+ */
+ if (cpu_wait == r4k_wait_irqoff)
+ set_bit(CPS_PM_NC_WAIT, state_support);
+ else
+ pr_warn("pm-cps: non-coherent wait unavailable\n");
+
+ /* Detect whether a CPC is present */
+ if (mips_cpc_present()) {
+ /* Detect whether clock gating is implemented */
+ if (read_cpc_cl_stat_conf() & CPC_Cx_STAT_CONF_CLKGAT_IMPL_MSK)
+ set_bit(CPS_PM_CLOCK_GATED, state_support);
+ else
+ pr_warn("pm-cps: CPC does not support clock gating\n");
+
+ /* Power gating is available with CPS SMP & any CPC */
+ if (mips_cps_smp_in_use())
+ set_bit(CPS_PM_POWER_GATED, state_support);
+ else
+ pr_warn("pm-cps: CPS SMP not in use, power gating unavailable\n");
+ } else {
+ pr_warn("pm-cps: no CPC, clock & power gating unavailable\n");
+ }
+
+ for_each_present_cpu(cpu) {
+ err = cps_gen_core_entries(cpu);
+ if (err)
+ return err;
+ }
+out:
+ return 0;
+}
+arch_initcall(cps_pm_init);
diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c
new file mode 100644
index 00000000000..fefdf39d3df
--- /dev/null
+++ b/arch/mips/kernel/pm.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ *
+ * 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.
+ *
+ * CPU PM notifiers for saving/restoring general CPU state.
+ */
+
+#include <linux/cpu_pm.h>
+#include <linux/init.h>
+
+#include <asm/dsp.h>
+#include <asm/fpu.h>
+#include <asm/mmu_context.h>
+#include <asm/pm.h>
+#include <asm/watch.h>
+
+/* Used by PM helper macros in asm/pm.h */
+struct mips_static_suspend_state mips_static_suspend_state;
+
+/**
+ * mips_cpu_save() - Save general CPU state.
+ * Ensures that general CPU context is saved, notably FPU and DSP.
+ */
+static int mips_cpu_save(void)
+{
+ /* Save FPU state */
+ lose_fpu(1);
+
+ /* Save DSP state */
+ save_dsp(current);
+
+ return 0;
+}
+
+/**
+ * mips_cpu_restore() - Restore general CPU state.
+ * Restores important CPU context.
+ */
+static void mips_cpu_restore(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ /* Restore ASID */
+ if (current->mm)
+ write_c0_entryhi(cpu_asid(cpu, current->mm));
+
+ /* Restore DSP state */
+ restore_dsp(current);
+
+ /* Restore UserLocal */
+ if (cpu_has_userlocal)
+ write_c0_userlocal(current_thread_info()->tp_value);
+
+ /* Restore watch registers */
+ __restore_watch();
+}
+
+/**
+ * mips_pm_notifier() - Notifier for preserving general CPU context.
+ * @self: Notifier block.
+ * @cmd: CPU PM event.
+ * @v: Private data (unused).
+ *
+ * This is called when a CPU power management event occurs, and is used to
+ * ensure that important CPU context is preserved across a CPU power down.
+ */
+static int mips_pm_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ int ret;
+
+ switch (cmd) {
+ case CPU_PM_ENTER:
+ ret = mips_cpu_save();
+ if (ret)
+ return NOTIFY_STOP;
+ break;
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ mips_cpu_restore();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block mips_pm_notifier_block = {
+ .notifier_call = mips_pm_notifier,
+};
+
+static int __init mips_pm_init(void)
+{
+ return cpu_pm_register_notifier(&mips_pm_notifier_block);
+}
+arch_initcall(mips_pm_init);
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 8c58d8a84bf..037a44d962f 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -17,8 +17,24 @@
unsigned int vced_count, vcei_count;
+/*
+ * * No lock; only written during early bootup by CPU 0.
+ * */
+static RAW_NOTIFIER_HEAD(proc_cpuinfo_chain);
+
+int __ref register_proc_cpuinfo_notifier(struct notifier_block *nb)
+{
+ return raw_notifier_chain_register(&proc_cpuinfo_chain, nb);
+}
+
+int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v)
+{
+ return raw_notifier_call_chain(&proc_cpuinfo_chain, val, v);
+}
+
static int show_cpuinfo(struct seq_file *m, void *v)
{
+ struct proc_cpuinfo_notifier_args proc_cpuinfo_notifier_args;
unsigned long n = (unsigned long) v - 1;
unsigned int version = cpu_data[n].processor_id;
unsigned int fp_vers = cpu_data[n].fpu_id;
@@ -65,26 +81,25 @@ static int show_cpuinfo(struct seq_file *m, void *v)
cpu_data[n].watch_reg_masks[i]);
seq_printf(m, "]\n");
}
- if (cpu_has_mips_r) {
- seq_printf(m, "isa\t\t\t: mips1");
- if (cpu_has_mips_2)
- seq_printf(m, "%s", " mips2");
- if (cpu_has_mips_3)
- seq_printf(m, "%s", " mips3");
- if (cpu_has_mips_4)
- seq_printf(m, "%s", " mips4");
- if (cpu_has_mips_5)
- seq_printf(m, "%s", " mips5");
- if (cpu_has_mips32r1)
- seq_printf(m, "%s", " mips32r1");
- if (cpu_has_mips32r2)
- seq_printf(m, "%s", " mips32r2");
- if (cpu_has_mips64r1)
- seq_printf(m, "%s", " mips64r1");
- if (cpu_has_mips64r2)
- seq_printf(m, "%s", " mips64r2");
- seq_printf(m, "\n");
- }
+
+ seq_printf(m, "isa\t\t\t: mips1");
+ if (cpu_has_mips_2)
+ seq_printf(m, "%s", " mips2");
+ if (cpu_has_mips_3)
+ seq_printf(m, "%s", " mips3");
+ if (cpu_has_mips_4)
+ seq_printf(m, "%s", " mips4");
+ if (cpu_has_mips_5)
+ seq_printf(m, "%s", " mips5");
+ if (cpu_has_mips32r1)
+ seq_printf(m, "%s", " mips32r1");
+ if (cpu_has_mips32r2)
+ seq_printf(m, "%s", " mips32r2");
+ if (cpu_has_mips64r1)
+ seq_printf(m, "%s", " mips64r1");
+ if (cpu_has_mips64r2)
+ seq_printf(m, "%s", " mips64r2");
+ seq_printf(m, "\n");
seq_printf(m, "ASEs implemented\t:");
if (cpu_has_mips16) seq_printf(m, "%s", " mips16");
@@ -96,6 +111,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (cpu_has_mipsmt) seq_printf(m, "%s", " mt");
if (cpu_has_mmips) seq_printf(m, "%s", " micromips");
if (cpu_has_vz) seq_printf(m, "%s", " vz");
+ if (cpu_has_msa) seq_printf(m, "%s", " msa");
+ if (cpu_has_eva) seq_printf(m, "%s", " eva");
seq_printf(m, "\n");
if (cpu_has_mmips) {
@@ -112,6 +129,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
cpu_has_vce ? "%u" : "not available");
seq_printf(m, fmt, 'D', vced_count);
seq_printf(m, fmt, 'I', vcei_count);
+
+ proc_cpuinfo_notifier_args.m = m;
+ proc_cpuinfo_notifier_args.n = n;
+
+ raw_notifier_call_chain(&proc_cpuinfo_chain, 0,
+ &proc_cpuinfo_notifier_args);
+
seq_printf(m, "\n");
return 0;
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index ddc76103e78..0a1ec0f3bef 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -32,6 +32,7 @@
#include <asm/cpu.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
+#include <asm/msa.h>
#include <asm/pgtable.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
@@ -60,15 +61,13 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
/* New thread loses kernel privileges. */
status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK);
-#ifdef CONFIG_64BIT
- status |= test_thread_flag(TIF_32BIT_REGS) ? 0 : ST0_FR;
-#endif
status |= KU_USER;
regs->cp0_status = status;
clear_used_math();
clear_fpu_owner();
- if (cpu_has_dsp)
- __init_dsp();
+ init_dsp();
+ clear_thread_flag(TIF_MSA_CTX_LIVE);
+ disable_msa();
regs->cp0_epc = pc;
regs->regs[29] = sp;
}
@@ -93,7 +92,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
preempt_disable();
- if (is_fpu_owner())
+ if (is_msa_enabled())
+ save_msa(p);
+ else if (is_fpu_owner())
save_fp(p);
if (cpu_has_dsp)
@@ -139,13 +140,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
*/
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC restores TCStatus after Status, and the CU bits
- * are aliased there.
- */
- childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1);
-#endif
clear_tsk_thread_flag(p, TIF_USEDFPU);
#ifdef CONFIG_MIPS_MT_FPAFF
@@ -161,7 +155,13 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
/* Fill in the fpu structure for a core dump.. */
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
{
- memcpy(r, &current->thread.fpu, sizeof(current->thread.fpu));
+ int i;
+
+ for (i = 0; i < NUM_FPU_REGS; i++)
+ memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
+
+ memcpy(&r[NUM_FPU_REGS], &current->thread.fpu.fcr31,
+ sizeof(current->thread.fpu.fcr31));
return 1;
}
@@ -196,7 +196,13 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
{
- memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu));
+ int i;
+
+ for (i = 0; i < NUM_FPU_REGS; i++)
+ memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr));
+
+ memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31,
+ sizeof(t->thread.fpu.fcr31));
return 1;
}
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index 0fa0b69cdd5..5d39bb85bf3 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -13,12 +13,9 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/bootmem.h>
-#include <linux/initrd.h>
#include <linux/debugfs.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
#include <asm/page.h>
#include <asm/prom.h>
@@ -40,13 +37,6 @@ char *mips_get_machine_name(void)
}
#ifdef CONFIG_OF
-int __init early_init_dt_scan_memory_arch(unsigned long node,
- const char *uname, int depth,
- void *data)
-{
- return early_init_dt_scan_memory(node, uname, depth, data);
-}
-
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
return add_memory_region(base, size, BOOT_MEM_RAM);
@@ -57,57 +47,11 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
}
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
- initrd_start = (unsigned long)__va(start);
- initrd_end = (unsigned long)__va(end);
- initrd_below_start_ok = 1;
-}
-#endif
-
-int __init early_init_dt_scan_model(unsigned long node, const char *uname,
- int depth, void *data)
-{
- if (!depth) {
- char *model = of_get_flat_dt_prop(node, "model", NULL);
-
- if (model)
- mips_set_machine_name(model);
- }
- return 0;
-}
-
-void __init early_init_devtree(void *params)
-{
- /* Setup flat device-tree pointer */
- initial_boot_params = params;
-
- /* Retrieve various informations from the /chosen node of the
- * device-tree, including the platform type, initrd location and
- * size, and more ...
- */
- of_scan_flat_dt(early_init_dt_scan_chosen, arcs_cmdline);
-
-
- /* Scan memory nodes */
- of_scan_flat_dt(early_init_dt_scan_root, NULL);
- of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
-
- /* try to load the mips machine name */
- of_scan_flat_dt(early_init_dt_scan_model, NULL);
-}
-
-void __init __dt_setup_arch(struct boot_param_header *bph)
+void __init __dt_setup_arch(void *bph)
{
- if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
- pr_err("DTB has bad magic, ignoring builtin OF DTB\n");
-
+ if (!early_init_dt_scan(bph))
return;
- }
-
- initial_boot_params = bph;
- early_init_devtree(initial_boot_params);
+ mips_set_machine_name(of_flat_dt_get_machine_name());
}
#endif
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8ae1ebef8b7..f639ccd5060 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -16,16 +16,20 @@
*/
#include <linux/compiler.h>
#include <linux/context_tracking.h>
+#include <linux/elf.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/regset.h>
#include <linux/smp.h>
#include <linux/user.h>
#include <linux/security.h>
+#include <linux/tracehook.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
+#include <linux/ftrace.h>
#include <asm/byteorder.h>
#include <asm/cpu.h>
@@ -35,10 +39,14 @@
#include <asm/mipsmtregs.h>
#include <asm/pgtable.h>
#include <asm/page.h>
+#include <asm/syscall.h>
#include <asm/uaccess.h>
#include <asm/bootinfo.h>
#include <asm/reg.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
/*
* Called by kernel/ptrace.c when detaching..
*
@@ -106,51 +114,30 @@ int ptrace_setregs(struct task_struct *child, __s64 __user *data)
int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
{
int i;
- unsigned int tmp;
if (!access_ok(VERIFY_WRITE, data, 33 * 8))
return -EIO;
if (tsk_used_math(child)) {
- fpureg_t *fregs = get_fpu_regs(child);
+ union fpureg *fregs = get_fpu_regs(child);
for (i = 0; i < 32; i++)
- __put_user(fregs[i], i + (__u64 __user *) data);
+ __put_user(get_fpr64(&fregs[i], 0),
+ i + (__u64 __user *)data);
} else {
for (i = 0; i < 32; i++)
__put_user((__u64) -1, i + (__u64 __user *) data);
}
__put_user(child->thread.fpu.fcr31, data + 64);
-
- preempt_disable();
- if (cpu_has_fpu) {
- unsigned int flags;
-
- if (cpu_has_mipsmt) {
- unsigned int vpflags = dvpe();
- flags = read_c0_status();
- __enable_fpu();
- __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
- write_c0_status(flags);
- evpe(vpflags);
- } else {
- flags = read_c0_status();
- __enable_fpu();
- __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
- write_c0_status(flags);
- }
- } else {
- tmp = 0;
- }
- preempt_enable();
- __put_user(tmp, data + 65);
+ __put_user(current_cpu_data.fpu_id, data + 65);
return 0;
}
int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
{
- fpureg_t *fregs;
+ union fpureg *fregs;
+ u64 fpr_val;
int i;
if (!access_ok(VERIFY_READ, data, 33 * 8))
@@ -158,8 +145,10 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
fregs = get_fpu_regs(child);
- for (i = 0; i < 32; i++)
- __get_user(fregs[i], i + (__u64 __user *) data);
+ for (i = 0; i < 32; i++) {
+ __get_user(fpr_val, i + (__u64 __user *)data);
+ set_fpr64(&fregs[i], 0, fpr_val);
+ }
__get_user(child->thread.fpu.fcr31, data + 64);
@@ -174,7 +163,7 @@ int ptrace_get_watch_regs(struct task_struct *child,
enum pt_watch_style style;
int i;
- if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
+ if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
return -EIO;
if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs)))
return -EIO;
@@ -188,14 +177,14 @@ int ptrace_get_watch_regs(struct task_struct *child,
#endif
__put_user(style, &addr->style);
- __put_user(current_cpu_data.watch_reg_use_cnt,
+ __put_user(boot_cpu_data.watch_reg_use_cnt,
&addr->WATCH_STYLE.num_valid);
- for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+ for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
__put_user(child->thread.watch.mips3264.watchlo[i],
&addr->WATCH_STYLE.watchlo[i]);
__put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff,
&addr->WATCH_STYLE.watchhi[i]);
- __put_user(current_cpu_data.watch_reg_masks[i],
+ __put_user(boot_cpu_data.watch_reg_masks[i],
&addr->WATCH_STYLE.watch_masks[i]);
}
for (; i < 8; i++) {
@@ -215,12 +204,12 @@ int ptrace_set_watch_regs(struct task_struct *child,
unsigned long lt[NUM_WATCH_REGS];
u16 ht[NUM_WATCH_REGS];
- if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
+ if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
return -EIO;
if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs)))
return -EIO;
/* Check the values. */
- for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+ for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
__get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]);
#ifdef CONFIG_32BIT
if (lt[i] & __UA_LIMIT)
@@ -239,7 +228,7 @@ int ptrace_set_watch_regs(struct task_struct *child,
return -EINVAL;
}
/* Install them. */
- for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+ for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
if (lt[i] & 7)
watch_active = 1;
child->thread.watch.mips3264.watchlo[i] = lt[i];
@@ -255,6 +244,167 @@ int ptrace_set_watch_regs(struct task_struct *child,
return 0;
}
+/* regset get/set implementations */
+
+static int gpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ regs, 0, sizeof(*regs));
+}
+
+static int gpr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct pt_regs newregs;
+ int ret;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &newregs,
+ 0, sizeof(newregs));
+ if (ret)
+ return ret;
+
+ *task_pt_regs(target) = newregs;
+
+ return 0;
+}
+
+static int fpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ unsigned i;
+ int err;
+ u64 fpr_val;
+
+ /* XXX fcr31 */
+
+ if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpu,
+ 0, sizeof(elf_fpregset_t));
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+ err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &fpr_val, i * sizeof(elf_fpreg_t),
+ (i + 1) * sizeof(elf_fpreg_t));
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int fpr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ unsigned i;
+ int err;
+ u64 fpr_val;
+
+ /* XXX fcr31 */
+
+ if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpu,
+ 0, sizeof(elf_fpregset_t));
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &fpr_val, i * sizeof(elf_fpreg_t),
+ (i + 1) * sizeof(elf_fpreg_t));
+ if (err)
+ return err;
+ set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+ }
+
+ return 0;
+}
+
+enum mips_regset {
+ REGSET_GPR,
+ REGSET_FPR,
+};
+
+static const struct user_regset mips_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(unsigned int),
+ .align = sizeof(unsigned int),
+ .get = gpr_get,
+ .set = gpr_set,
+ },
+ [REGSET_FPR] = {
+ .core_note_type = NT_PRFPREG,
+ .n = ELF_NFPREG,
+ .size = sizeof(elf_fpreg_t),
+ .align = sizeof(elf_fpreg_t),
+ .get = fpr_get,
+ .set = fpr_set,
+ },
+};
+
+static const struct user_regset_view user_mips_view = {
+ .name = "mips",
+ .e_machine = ELF_ARCH,
+ .ei_osabi = ELF_OSABI,
+ .regsets = mips_regsets,
+ .n = ARRAY_SIZE(mips_regsets),
+};
+
+static const struct user_regset mips64_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(unsigned long),
+ .align = sizeof(unsigned long),
+ .get = gpr_get,
+ .set = gpr_set,
+ },
+ [REGSET_FPR] = {
+ .core_note_type = NT_PRFPREG,
+ .n = ELF_NFPREG,
+ .size = sizeof(elf_fpreg_t),
+ .align = sizeof(elf_fpreg_t),
+ .get = fpr_get,
+ .set = fpr_set,
+ },
+};
+
+static const struct user_regset_view user_mips64_view = {
+ .name = "mips",
+ .e_machine = ELF_ARCH,
+ .ei_osabi = ELF_OSABI,
+ .regsets = mips64_regsets,
+ .n = ARRAY_SIZE(mips_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_32BIT
+ return &user_mips_view;
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+ if (test_thread_flag(TIF_32BIT_REGS))
+ return &user_mips_view;
+#endif
+
+ return &user_mips64_view;
+}
+
long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -273,6 +423,7 @@ long arch_ptrace(struct task_struct *child, long request,
/* Read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
struct pt_regs *regs;
+ union fpureg *fregs;
unsigned long tmp = 0;
regs = task_pt_regs(child);
@@ -283,26 +434,26 @@ long arch_ptrace(struct task_struct *child, long request,
tmp = regs->regs[addr];
break;
case FPR_BASE ... FPR_BASE + 31:
- if (tsk_used_math(child)) {
- fpureg_t *fregs = get_fpu_regs(child);
+ if (!tsk_used_math(child)) {
+ /* FP not yet used */
+ tmp = -1;
+ break;
+ }
+ fregs = get_fpu_regs(child);
#ifdef CONFIG_32BIT
+ if (test_thread_flag(TIF_32BIT_FPREGS)) {
/*
* The odd registers are actually the high
* order bits of the values stored in the even
* registers - unless we're using r2k_switch.S.
*/
- if (addr & 1)
- tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32);
- else
- tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
-#endif
-#ifdef CONFIG_64BIT
- tmp = fregs[addr - FPR_BASE];
-#endif
- } else {
- tmp = -1; /* FP not yet used */
+ tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+ addr & 1);
+ break;
}
+#endif
+ tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
break;
case PC:
tmp = regs->cp0_epc;
@@ -327,44 +478,10 @@ long arch_ptrace(struct task_struct *child, long request,
case FPC_CSR:
tmp = child->thread.fpu.fcr31;
break;
- case FPC_EIR: { /* implementation / version register */
- unsigned int flags;
-#ifdef CONFIG_MIPS_MT_SMTC
- unsigned long irqflags;
- unsigned int mtflags;
-#endif /* CONFIG_MIPS_MT_SMTC */
-
- preempt_disable();
- if (!cpu_has_fpu) {
- preempt_enable();
- break;
- }
-
-#ifdef CONFIG_MIPS_MT_SMTC
- /* Read-modify-write of Status must be atomic */
- local_irq_save(irqflags);
- mtflags = dmt();
-#endif /* CONFIG_MIPS_MT_SMTC */
- if (cpu_has_mipsmt) {
- unsigned int vpflags = dvpe();
- flags = read_c0_status();
- __enable_fpu();
- __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
- write_c0_status(flags);
- evpe(vpflags);
- } else {
- flags = read_c0_status();
- __enable_fpu();
- __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
- write_c0_status(flags);
- }
-#ifdef CONFIG_MIPS_MT_SMTC
- emt(mtflags);
- local_irq_restore(irqflags);
-#endif /* CONFIG_MIPS_MT_SMTC */
- preempt_enable();
+ case FPC_EIR:
+ /* implementation / version register */
+ tmp = current_cpu_data.fpu_id;
break;
- }
case DSP_BASE ... DSP_BASE + 5: {
dspreg_t *dregs;
@@ -410,7 +527,7 @@ long arch_ptrace(struct task_struct *child, long request,
regs->regs[addr] = data;
break;
case FPR_BASE ... FPR_BASE + 31: {
- fpureg_t *fregs = get_fpu_regs(child);
+ union fpureg *fregs = get_fpu_regs(child);
if (!tsk_used_math(child)) {
/* FP not yet used */
@@ -419,22 +536,18 @@ long arch_ptrace(struct task_struct *child, long request,
child->thread.fpu.fcr31 = 0;
}
#ifdef CONFIG_32BIT
- /*
- * The odd registers are actually the high order bits
- * of the values stored in the even registers - unless
- * we're using r2k_switch.S.
- */
- if (addr & 1) {
- fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff;
- fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32;
- } else {
- fregs[addr - FPR_BASE] &= ~0xffffffffLL;
- fregs[addr - FPR_BASE] |= data;
+ if (test_thread_flag(TIF_32BIT_FPREGS)) {
+ /*
+ * The odd registers are actually the high
+ * order bits of the values stored in the even
+ * registers - unless we're using r2k_switch.S.
+ */
+ set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+ addr & 1, data);
+ break;
}
#endif
-#ifdef CONFIG_64BIT
- fregs[addr - FPR_BASE] = data;
-#endif
+ set_fpr64(&fregs[addr - FPR_BASE], 0, data);
break;
}
case PC:
@@ -517,54 +630,30 @@ long arch_ptrace(struct task_struct *child, long request,
return ret;
}
-static inline int audit_arch(void)
-{
- int arch = EM_MIPS;
-#ifdef CONFIG_64BIT
- arch |= __AUDIT_ARCH_64BIT;
-#endif
-#if defined(__LITTLE_ENDIAN)
- arch |= __AUDIT_ARCH_LE;
-#endif
- return arch;
-}
-
/*
* Notification of system call entry/exit
* - triggered by current->work.syscall_trace
*/
-asmlinkage void syscall_trace_enter(struct pt_regs *regs)
+asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
{
+ long ret = 0;
user_exit();
- /* do the secure computing check first */
- secure_computing_strict(regs->regs[2]);
-
- if (!(current->ptrace & PT_PTRACED))
- goto out;
-
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- goto out;
+ if (secure_computing(syscall) == -1)
+ return -1;
- /* The 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
- 0x80 : 0));
+ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+ tracehook_report_syscall_entry(regs))
+ ret = -1;
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
+ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+ trace_sys_enter(regs, regs->regs[2]);
-out:
- audit_syscall_entry(audit_arch(), regs->regs[2],
+ audit_syscall_entry(syscall_get_arch(),
+ syscall,
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
+ return syscall;
}
/*
@@ -582,26 +671,11 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
audit_syscall_exit(regs);
- if (!(current->ptrace & PT_PTRACED))
- return;
+ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+ trace_sys_exit(regs, regs->regs[2]);
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
-
- /* The 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
- 0x80 : 0));
-
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
+ if (test_thread_flag(TIF_SYSCALL_TRACE))
+ tracehook_report_syscall_exit(regs, 0);
user_enter();
}
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 9486055ba66..b40c3ca60ee 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -80,6 +80,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
/* Read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
struct pt_regs *regs;
+ union fpureg *fregs;
unsigned int tmp;
regs = task_pt_regs(child);
@@ -90,21 +91,23 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
tmp = regs->regs[addr];
break;
case FPR_BASE ... FPR_BASE + 31:
- if (tsk_used_math(child)) {
- fpureg_t *fregs = get_fpu_regs(child);
-
+ if (!tsk_used_math(child)) {
+ /* FP not yet used */
+ tmp = -1;
+ break;
+ }
+ fregs = get_fpu_regs(child);
+ if (test_thread_flag(TIF_32BIT_FPREGS)) {
/*
* The odd registers are actually the high
* order bits of the values stored in the even
* registers - unless we're using r2k_switch.S.
*/
- if (addr & 1)
- tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32);
- else
- tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
- } else {
- tmp = -1; /* FP not yet used */
+ tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+ addr & 1);
+ break;
}
+ tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
break;
case PC:
tmp = regs->cp0_epc;
@@ -124,46 +127,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
case FPC_CSR:
tmp = child->thread.fpu.fcr31;
break;
- case FPC_EIR: { /* implementation / version register */
- unsigned int flags;
-#ifdef CONFIG_MIPS_MT_SMTC
- unsigned int irqflags;
- unsigned int mtflags;
-#endif /* CONFIG_MIPS_MT_SMTC */
-
- preempt_disable();
- if (!cpu_has_fpu) {
- preempt_enable();
- tmp = 0;
- break;
- }
-
-#ifdef CONFIG_MIPS_MT_SMTC
- /* Read-modify-write of Status must be atomic */
- local_irq_save(irqflags);
- mtflags = dmt();
-#endif /* CONFIG_MIPS_MT_SMTC */
-
- if (cpu_has_mipsmt) {
- unsigned int vpflags = dvpe();
- flags = read_c0_status();
- __enable_fpu();
- __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
- write_c0_status(flags);
- evpe(vpflags);
- } else {
- flags = read_c0_status();
- __enable_fpu();
- __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
- write_c0_status(flags);
- }
-#ifdef CONFIG_MIPS_MT_SMTC
- emt(mtflags);
- local_irq_restore(irqflags);
-#endif /* CONFIG_MIPS_MT_SMTC */
- preempt_enable();
+ case FPC_EIR:
+ /* implementation / version register */
+ tmp = current_cpu_data.fpu_id;
break;
- }
case DSP_BASE ... DSP_BASE + 5: {
dspreg_t *dregs;
@@ -228,7 +195,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
regs->regs[addr] = data;
break;
case FPR_BASE ... FPR_BASE + 31: {
- fpureg_t *fregs = get_fpu_regs(child);
+ union fpureg *fregs = get_fpu_regs(child);
if (!tsk_used_math(child)) {
/* FP not yet used */
@@ -236,20 +203,17 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
sizeof(child->thread.fpu));
child->thread.fpu.fcr31 = 0;
}
- /*
- * The odd registers are actually the high order bits
- * of the values stored in the even registers - unless
- * we're using r2k_switch.S.
- */
- if (addr & 1) {
- fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff;
- fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32;
- } else {
- fregs[addr - FPR_BASE] &= ~0xffffffffLL;
- /* Must cast, lest sign extension fill upper
- bits! */
- fregs[addr - FPR_BASE] |= (unsigned int)data;
+ if (test_thread_flag(TIF_32BIT_FPREGS)) {
+ /*
+ * The odd registers are actually the high
+ * order bits of the values stored in the even
+ * registers - unless we're using r2k_switch.S.
+ */
+ set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
+ addr & 1, data);
+ break;
}
+ set_fpr64(&fregs[addr - FPR_BASE], 0, data);
break;
}
case PC:
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index 38af83f84c4..20b7b040e76 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -67,7 +67,7 @@ LEAF(resume)
1:
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
- PTR_L t8, __stack_chk_guard
+ PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
LONG_S t9, 0(t8)
#endif
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 55ffe149dae..8352523568e 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -30,12 +30,20 @@
.endm
.set noreorder
- .set mips3
+ .set arch=r4000
LEAF(_save_fp_context)
cfc1 t1, fcr31
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+ .set push
+#ifdef CONFIG_CPU_MIPS32_R2
+ .set mips64r2
+ mfc0 t0, CP0_STATUS
+ sll t0, t0, 5
+ bgez t0, 1f # skip storing odd if FR=0
+ nop
+#endif
/* Store the 16 odd double precision registers */
EX sdc1 $f1, SC_FPREGS+8(a0)
EX sdc1 $f3, SC_FPREGS+24(a0)
@@ -53,6 +61,7 @@ LEAF(_save_fp_context)
EX sdc1 $f27, SC_FPREGS+216(a0)
EX sdc1 $f29, SC_FPREGS+232(a0)
EX sdc1 $f31, SC_FPREGS+248(a0)
+1: .set pop
#endif
/* Store the 16 even double precision registers */
@@ -82,7 +91,31 @@ LEAF(_save_fp_context)
LEAF(_save_fp_context32)
cfc1 t1, fcr31
- EX sdc1 $f0, SC32_FPREGS+0(a0)
+ mfc0 t0, CP0_STATUS
+ sll t0, t0, 5
+ bgez t0, 1f # skip storing odd if FR=0
+ nop
+
+ /* Store the 16 odd double precision registers */
+ EX sdc1 $f1, SC32_FPREGS+8(a0)
+ EX sdc1 $f3, SC32_FPREGS+24(a0)
+ EX sdc1 $f5, SC32_FPREGS+40(a0)
+ EX sdc1 $f7, SC32_FPREGS+56(a0)
+ EX sdc1 $f9, SC32_FPREGS+72(a0)
+ EX sdc1 $f11, SC32_FPREGS+88(a0)
+ EX sdc1 $f13, SC32_FPREGS+104(a0)
+ EX sdc1 $f15, SC32_FPREGS+120(a0)
+ EX sdc1 $f17, SC32_FPREGS+136(a0)
+ EX sdc1 $f19, SC32_FPREGS+152(a0)
+ EX sdc1 $f21, SC32_FPREGS+168(a0)
+ EX sdc1 $f23, SC32_FPREGS+184(a0)
+ EX sdc1 $f25, SC32_FPREGS+200(a0)
+ EX sdc1 $f27, SC32_FPREGS+216(a0)
+ EX sdc1 $f29, SC32_FPREGS+232(a0)
+ EX sdc1 $f31, SC32_FPREGS+248(a0)
+
+ /* Store the 16 even double precision registers */
+1: EX sdc1 $f0, SC32_FPREGS+0(a0)
EX sdc1 $f2, SC32_FPREGS+16(a0)
EX sdc1 $f4, SC32_FPREGS+32(a0)
EX sdc1 $f6, SC32_FPREGS+48(a0)
@@ -113,8 +146,17 @@ LEAF(_save_fp_context32)
* - cp1 status/control register
*/
LEAF(_restore_fp_context)
- EX lw t0, SC_FPC_CSR(a0)
-#ifdef CONFIG_64BIT
+ EX lw t1, SC_FPC_CSR(a0)
+
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
+ .set push
+#ifdef CONFIG_CPU_MIPS32_R2
+ .set mips64r2
+ mfc0 t0, CP0_STATUS
+ sll t0, t0, 5
+ bgez t0, 1f # skip loading odd if FR=0
+ nop
+#endif
EX ldc1 $f1, SC_FPREGS+8(a0)
EX ldc1 $f3, SC_FPREGS+24(a0)
EX ldc1 $f5, SC_FPREGS+40(a0)
@@ -131,6 +173,7 @@ LEAF(_restore_fp_context)
EX ldc1 $f27, SC_FPREGS+216(a0)
EX ldc1 $f29, SC_FPREGS+232(a0)
EX ldc1 $f31, SC_FPREGS+248(a0)
+1: .set pop
#endif
EX ldc1 $f0, SC_FPREGS+0(a0)
EX ldc1 $f2, SC_FPREGS+16(a0)
@@ -148,7 +191,7 @@ LEAF(_restore_fp_context)
EX ldc1 $f26, SC_FPREGS+208(a0)
EX ldc1 $f28, SC_FPREGS+224(a0)
EX ldc1 $f30, SC_FPREGS+240(a0)
- ctc1 t0, fcr31
+ ctc1 t1, fcr31
jr ra
li v0, 0 # success
END(_restore_fp_context)
@@ -156,8 +199,31 @@ LEAF(_restore_fp_context)
#ifdef CONFIG_MIPS32_COMPAT
LEAF(_restore_fp_context32)
/* Restore an o32 sigcontext. */
- EX lw t0, SC32_FPC_CSR(a0)
- EX ldc1 $f0, SC32_FPREGS+0(a0)
+ EX lw t1, SC32_FPC_CSR(a0)
+
+ mfc0 t0, CP0_STATUS
+ sll t0, t0, 5
+ bgez t0, 1f # skip loading odd if FR=0
+ nop
+
+ EX ldc1 $f1, SC32_FPREGS+8(a0)
+ EX ldc1 $f3, SC32_FPREGS+24(a0)
+ EX ldc1 $f5, SC32_FPREGS+40(a0)
+ EX ldc1 $f7, SC32_FPREGS+56(a0)
+ EX ldc1 $f9, SC32_FPREGS+72(a0)
+ EX ldc1 $f11, SC32_FPREGS+88(a0)
+ EX ldc1 $f13, SC32_FPREGS+104(a0)
+ EX ldc1 $f15, SC32_FPREGS+120(a0)
+ EX ldc1 $f17, SC32_FPREGS+136(a0)
+ EX ldc1 $f19, SC32_FPREGS+152(a0)
+ EX ldc1 $f21, SC32_FPREGS+168(a0)
+ EX ldc1 $f23, SC32_FPREGS+184(a0)
+ EX ldc1 $f25, SC32_FPREGS+200(a0)
+ EX ldc1 $f27, SC32_FPREGS+216(a0)
+ EX ldc1 $f29, SC32_FPREGS+232(a0)
+ EX ldc1 $f31, SC32_FPREGS+248(a0)
+
+1: EX ldc1 $f0, SC32_FPREGS+0(a0)
EX ldc1 $f2, SC32_FPREGS+16(a0)
EX ldc1 $f4, SC32_FPREGS+32(a0)
EX ldc1 $f6, SC32_FPREGS+48(a0)
@@ -173,7 +239,7 @@ LEAF(_restore_fp_context32)
EX ldc1 $f26, SC32_FPREGS+208(a0)
EX ldc1 $f28, SC32_FPREGS+224(a0)
EX ldc1 $f30, SC32_FPREGS+240(a0)
- ctc1 t0, fcr31
+ ctc1 t1, fcr31
jr ra
li v0, 0 # success
END(_restore_fp_context32)
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 921238a6bd2..81ca3f70fe2 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -28,19 +28,10 @@
*/
#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.
- */
-
+#ifndef USE_ALTERNATE_RESUME_IMPL
/*
* task_struct *resume(task_struct *prev, task_struct *next,
- * struct thread_info *next_ti, int usedfpu)
+ * struct thread_info *next_ti, s32 fp_save)
*/
.align 5
LEAF(resume)
@@ -50,26 +41,40 @@
LONG_S ra, THREAD_REG31(a0)
/*
- * check if we need to save FPU registers
+ * 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
- beqz a3, 1f
-
- PTR_L t3, TASK_THREAD_INFO(a0)
/*
- * clear saved user stack CU1 bit
+ * 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. */
+ msa_save_all a0
+ b 2f
+
+1: /* Save 32b/64b scalar FP context. */
fpu_save_double a0 t0 t1 # c0_status passed in t0
# clobbers t1
-1:
+2:
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
- PTR_L t8, __stack_chk_guard
+ PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
LONG_S t9, 0(t8)
#endif
@@ -83,18 +88,6 @@
PTR_ADDU t0, $28, _THREAD_SIZE - 32
set_saved_sp t0, t1, t2
-#ifdef CONFIG_MIPS_MT_SMTC
- /* Read-modify-writes of Status must be atomic on a VPE */
- mfc0 t2, CP0_TCSTATUS
- ori t1, t2, TCSTATUS_IXMT
- mtc0 t1, CP0_TCSTATUS
- andi t2, t2, TCSTATUS_IXMT
- _ehb
- DMT 8 # dmt t0
- move t1,ra
- jal mips_ihb
- move ra,t1
-#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t1, CP0_STATUS /* Do we really need this? */
li a3, 0xff01
and t1, a3
@@ -103,27 +96,17 @@
and a2, a3
or a2, t1
mtc0 a2, CP0_STATUS
-#ifdef CONFIG_MIPS_MT_SMTC
- _ehb
- andi t0, t0, VPECONTROL_TE
- beqz t0, 1f
- emt
-1:
- mfc0 t1, CP0_TCSTATUS
- xori t1, t1, TCSTATUS_IXMT
- or t1, t1, t2
- mtc0 t1, CP0_TCSTATUS
- _ehb
-#endif /* CONFIG_MIPS_MT_SMTC */
move v0, a0
jr ra
END(resume)
+#endif /* USE_ALTERNATE_RESUME_IMPL */
+
/*
* Save a thread's fp context.
*/
LEAF(_save_fp)
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
mfc0 t0, CP0_STATUS
#endif
fpu_save_double a0 t0 t1 # clobbers t1
@@ -134,13 +117,33 @@ LEAF(_save_fp)
* Restore a thread's fp context.
*/
LEAF(_restore_fp)
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
mfc0 t0, CP0_STATUS
#endif
fpu_restore_double a0 t0 t1 # clobbers t1
jr ra
END(_restore_fp)
+#ifdef CONFIG_CPU_HAS_MSA
+
+/*
+ * Save a thread's MSA vector context.
+ */
+LEAF(_save_msa)
+ msa_save_all a0
+ jr ra
+ END(_save_msa)
+
+/*
+ * Restore a thread's MSA vector context.
+ */
+LEAF(_restore_msa)
+ msa_restore_all a0
+ jr ra
+ END(_restore_msa)
+
+#endif
+
/*
* Load the FPU with signalling NANS. This bit pattern we're using has
* the property that no matter whether considered as single or as double
@@ -152,19 +155,10 @@ LEAF(_restore_fp)
#define FPU_DEFAULT 0x00000000
LEAF(_init_fpu)
-#ifdef CONFIG_MIPS_MT_SMTC
- /* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */
- mfc0 t0, CP0_TCSTATUS
- /* Bit position is the same for Status, TCStatus */
- li t1, ST0_CU1
- or t0, t1
- mtc0 t0, CP0_TCSTATUS
-#else /* Normal MIPS CU1 enable */
mfc0 t0, CP0_STATUS
li t1, ST0_CU1
or t0, t1
mtc0 t0, CP0_STATUS
-#endif /* CONFIG_MIPS_MT_SMTC */
enable_fpu_hazard
li t1, FPU_DEFAULT
@@ -228,8 +222,49 @@ LEAF(_init_fpu)
mtc1 t1, $f29
mtc1 t1, $f30
mtc1 t1, $f31
+
+#ifdef CONFIG_CPU_MIPS32_R2
+ .set push
+ .set mips64r2
+ sll t0, t0, 5 # is Status.FR set?
+ bgez t0, 1f # no: skip setting upper 32b
+
+ mthc1 t1, $f0
+ mthc1 t1, $f1
+ mthc1 t1, $f2
+ mthc1 t1, $f3
+ mthc1 t1, $f4
+ mthc1 t1, $f5
+ mthc1 t1, $f6
+ mthc1 t1, $f7
+ mthc1 t1, $f8
+ mthc1 t1, $f9
+ mthc1 t1, $f10
+ mthc1 t1, $f11
+ mthc1 t1, $f12
+ mthc1 t1, $f13
+ mthc1 t1, $f14
+ mthc1 t1, $f15
+ mthc1 t1, $f16
+ mthc1 t1, $f17
+ mthc1 t1, $f18
+ mthc1 t1, $f19
+ mthc1 t1, $f20
+ mthc1 t1, $f21
+ mthc1 t1, $f22
+ mthc1 t1, $f23
+ mthc1 t1, $f24
+ mthc1 t1, $f25
+ mthc1 t1, $f26
+ mthc1 t1, $f27
+ mthc1 t1, $f28
+ mthc1 t1, $f29
+ mthc1 t1, $f30
+ mthc1 t1, $f31
+1: .set pop
+#endif /* CONFIG_CPU_MIPS32_R2 */
#else
- .set mips3
+ .set arch=r4000
dmtc1 t1, $f0
dmtc1 t1, $f2
dmtc1 t1, $f4
diff --git a/arch/mips/kernel/rtlx-cmp.c b/arch/mips/kernel/rtlx-cmp.c
new file mode 100644
index 00000000000..758fb3cd232
--- /dev/null
+++ b/arch/mips/kernel/rtlx-cmp.c
@@ -0,0 +1,119 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+
+#include <asm/mips_mt.h>
+#include <asm/vpe.h>
+#include <asm/rtlx.h>
+
+static int major;
+
+static void rtlx_interrupt(void)
+{
+ int i;
+ struct rtlx_info *info;
+ struct rtlx_info **p = vpe_get_shared(aprp_cpu_index());
+
+ if (p == NULL || *p == NULL)
+ return;
+
+ info = *p;
+
+ if (info->ap_int_pending == 1 && smp_processor_id() == 0) {
+ for (i = 0; i < RTLX_CHANNELS; i++) {
+ wake_up(&channel_wqs[i].lx_queue);
+ wake_up(&channel_wqs[i].rt_queue);
+ }
+ info->ap_int_pending = 0;
+ }
+}
+
+void _interrupt_sp(void)
+{
+ smp_send_reschedule(aprp_cpu_index());
+}
+
+int __init rtlx_module_init(void)
+{
+ struct device *dev;
+ int i, err;
+
+ if (!cpu_has_mipsmt) {
+ pr_warn("VPE loader: not a MIPS MT capable processor\n");
+ return -ENODEV;
+ }
+
+ if (num_possible_cpus() - aprp_cpu_index() < 1) {
+ pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n"
+ "Pass maxcpus=<n> argument as kernel argument\n");
+
+ return -ENODEV;
+ }
+
+ major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops);
+ if (major < 0) {
+ pr_err("rtlx_module_init: unable to register device\n");
+ return major;
+ }
+
+ /* initialise the wait queues */
+ for (i = 0; i < RTLX_CHANNELS; i++) {
+ init_waitqueue_head(&channel_wqs[i].rt_queue);
+ init_waitqueue_head(&channel_wqs[i].lx_queue);
+ atomic_set(&channel_wqs[i].in_open, 0);
+ mutex_init(&channel_wqs[i].mutex);
+
+ dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
+ "%s%d", RTLX_MODULE_NAME, i);
+ if (IS_ERR(dev)) {
+ err = PTR_ERR(dev);
+ goto out_chrdev;
+ }
+ }
+
+ /* set up notifiers */
+ rtlx_notify.start = rtlx_starting;
+ rtlx_notify.stop = rtlx_stopping;
+ vpe_notify(aprp_cpu_index(), &rtlx_notify);
+
+ if (cpu_has_vint) {
+ aprp_hook = rtlx_interrupt;
+ } else {
+ pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
+ err = -ENODEV;
+ goto out_class;
+ }
+
+ return 0;
+
+out_class:
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ device_destroy(mt_class, MKDEV(major, i));
+out_chrdev:
+ unregister_chrdev(major, RTLX_MODULE_NAME);
+
+ return err;
+}
+
+void __exit rtlx_module_exit(void)
+{
+ int i;
+
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ device_destroy(mt_class, MKDEV(major, i));
+
+ unregister_chrdev(major, RTLX_MODULE_NAME);
+
+ aprp_hook = NULL;
+}
diff --git a/arch/mips/kernel/rtlx-mt.c b/arch/mips/kernel/rtlx-mt.c
new file mode 100644
index 00000000000..5a66b975989
--- /dev/null
+++ b/arch/mips/kernel/rtlx-mt.c
@@ -0,0 +1,150 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/mips_mt.h>
+#include <asm/vpe.h>
+#include <asm/rtlx.h>
+
+static int major;
+
+static void rtlx_dispatch(void)
+{
+ if (read_c0_cause() & read_c0_status() & C_SW0)
+ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
+}
+
+/*
+ * Interrupt handler may be called before rtlx_init has otherwise had
+ * a chance to run.
+ */
+static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
+{
+ unsigned int vpeflags;
+ unsigned long flags;
+ int i;
+
+ local_irq_save(flags);
+ vpeflags = dvpe();
+ set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ);
+ irq_enable_hazard();
+ evpe(vpeflags);
+ local_irq_restore(flags);
+
+ for (i = 0; i < RTLX_CHANNELS; i++) {
+ wake_up(&channel_wqs[i].lx_queue);
+ wake_up(&channel_wqs[i].rt_queue);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction rtlx_irq = {
+ .handler = rtlx_interrupt,
+ .name = "RTLX",
+};
+
+static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
+
+void _interrupt_sp(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ dvpe();
+ settc(1);
+ write_vpe_c0_cause(read_vpe_c0_cause() | C_SW0);
+ evpe(EVPE_ENABLE);
+ local_irq_restore(flags);
+}
+
+int __init rtlx_module_init(void)
+{
+ struct device *dev;
+ int i, err;
+
+ if (!cpu_has_mipsmt) {
+ pr_warn("VPE loader: not a MIPS MT capable processor\n");
+ return -ENODEV;
+ }
+
+ if (aprp_cpu_index() == 0) {
+ pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n"
+ "Pass maxtcs=<n> argument as kernel argument\n");
+
+ return -ENODEV;
+ }
+
+ major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops);
+ if (major < 0) {
+ pr_err("rtlx_module_init: unable to register device\n");
+ return major;
+ }
+
+ /* initialise the wait queues */
+ for (i = 0; i < RTLX_CHANNELS; i++) {
+ init_waitqueue_head(&channel_wqs[i].rt_queue);
+ init_waitqueue_head(&channel_wqs[i].lx_queue);
+ atomic_set(&channel_wqs[i].in_open, 0);
+ mutex_init(&channel_wqs[i].mutex);
+
+ dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
+ "%s%d", RTLX_MODULE_NAME, i);
+ if (IS_ERR(dev)) {
+ err = PTR_ERR(dev);
+ goto out_chrdev;
+ }
+ }
+
+ /* set up notifiers */
+ rtlx_notify.start = rtlx_starting;
+ rtlx_notify.stop = rtlx_stopping;
+ vpe_notify(aprp_cpu_index(), &rtlx_notify);
+
+ if (cpu_has_vint) {
+ aprp_hook = rtlx_dispatch;
+ } else {
+ pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
+ err = -ENODEV;
+ goto out_class;
+ }
+
+ rtlx_irq.dev_id = rtlx;
+ err = setup_irq(rtlx_irq_num, &rtlx_irq);
+ if (err)
+ goto out_class;
+
+ return 0;
+
+out_class:
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ device_destroy(mt_class, MKDEV(major, i));
+out_chrdev:
+ unregister_chrdev(major, RTLX_MODULE_NAME);
+
+ return err;
+}
+
+void __exit rtlx_module_exit(void)
+{
+ int i;
+
+ for (i = 0; i < RTLX_CHANNELS; i++)
+ device_destroy(mt_class, MKDEV(major, i));
+
+ unregister_chrdev(major, RTLX_MODULE_NAME);
+
+ aprp_hook = NULL;
+}
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index d763f11e35e..31b1b763cb2 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -1,114 +1,51 @@
/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
* Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
* Copyright (C) 2005, 06 Ralf Baechle (ralf@linux-mips.org)
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*/
-
-#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/fs.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/elf.h>
-#include <linux/seq_file.h>
#include <linux/syscalls.h>
#include <linux/moduleloader.h>
-#include <linux/interrupt.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
+#include <linux/atomic.h>
#include <asm/mipsmtregs.h>
#include <asm/mips_mt.h>
-#include <asm/cacheflush.h>
-#include <linux/atomic.h>
-#include <asm/cpu.h>
#include <asm/processor.h>
-#include <asm/vpe.h>
#include <asm/rtlx.h>
#include <asm/setup.h>
+#include <asm/vpe.h>
-static struct rtlx_info *rtlx;
-static int major;
-static char module_name[] = "rtlx";
-
-static struct chan_waitqueues {
- wait_queue_head_t rt_queue;
- wait_queue_head_t lx_queue;
- atomic_t in_open;
- struct mutex mutex;
-} channel_wqs[RTLX_CHANNELS];
-
-static struct vpe_notifications notify;
static int sp_stopping;
-
-extern void *vpe_get_shared(int index);
-
-static void rtlx_dispatch(void)
-{
- do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
-}
-
-
-/* Interrupt handler may be called before rtlx_init has otherwise had
- a chance to run.
-*/
-static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
-{
- unsigned int vpeflags;
- unsigned long flags;
- int i;
-
- /* Ought not to be strictly necessary for SMTC builds */
- local_irq_save(flags);
- vpeflags = dvpe();
- set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ);
- irq_enable_hazard();
- evpe(vpeflags);
- local_irq_restore(flags);
-
- for (i = 0; i < RTLX_CHANNELS; i++) {
- wake_up(&channel_wqs[i].lx_queue);
- wake_up(&channel_wqs[i].rt_queue);
- }
-
- return IRQ_HANDLED;
-}
+struct rtlx_info *rtlx;
+struct chan_waitqueues channel_wqs[RTLX_CHANNELS];
+struct vpe_notifications rtlx_notify;
+void (*aprp_hook)(void) = NULL;
+EXPORT_SYMBOL(aprp_hook);
static void __used dump_rtlx(void)
{
int i;
- printk("id 0x%lx state %d\n", rtlx->id, rtlx->state);
+ pr_info("id 0x%lx state %d\n", rtlx->id, rtlx->state);
for (i = 0; i < RTLX_CHANNELS; i++) {
struct rtlx_channel *chan = &rtlx->channel[i];
- printk(" rt_state %d lx_state %d buffer_size %d\n",
- chan->rt_state, chan->lx_state, chan->buffer_size);
+ pr_info(" rt_state %d lx_state %d buffer_size %d\n",
+ chan->rt_state, chan->lx_state, chan->buffer_size);
- printk(" rt_read %d rt_write %d\n",
- chan->rt_read, chan->rt_write);
+ pr_info(" rt_read %d rt_write %d\n",
+ chan->rt_read, chan->rt_write);
- printk(" lx_read %d lx_write %d\n",
- chan->lx_read, chan->lx_write);
+ pr_info(" lx_read %d lx_write %d\n",
+ chan->lx_read, chan->lx_write);
- printk(" rt_buffer <%s>\n", chan->rt_buffer);
- printk(" lx_buffer <%s>\n", chan->lx_buffer);
+ pr_info(" rt_buffer <%s>\n", chan->rt_buffer);
+ pr_info(" lx_buffer <%s>\n", chan->lx_buffer);
}
}
@@ -116,8 +53,7 @@ static void __used dump_rtlx(void)
static int rtlx_init(struct rtlx_info *rtlxi)
{
if (rtlxi->id != RTLX_ID) {
- printk(KERN_ERR "no valid RTLX id at 0x%p 0x%lx\n",
- rtlxi, rtlxi->id);
+ pr_err("no valid RTLX id at 0x%p 0x%lx\n", rtlxi, rtlxi->id);
return -ENOEXEC;
}
@@ -127,20 +63,20 @@ static int rtlx_init(struct rtlx_info *rtlxi)
}
/* notifications */
-static void starting(int vpe)
+void rtlx_starting(int vpe)
{
int i;
sp_stopping = 0;
/* force a reload of rtlx */
- rtlx=NULL;
+ rtlx = NULL;
/* wake up any sleeping rtlx_open's */
for (i = 0; i < RTLX_CHANNELS; i++)
wake_up_interruptible(&channel_wqs[i].lx_queue);
}
-static void stopping(int vpe)
+void rtlx_stopping(int vpe)
{
int i;
@@ -158,30 +94,30 @@ int rtlx_open(int index, int can_sleep)
int ret = 0;
if (index >= RTLX_CHANNELS) {
- printk(KERN_DEBUG "rtlx_open index out of range\n");
+ pr_debug(KERN_DEBUG "rtlx_open index out of range\n");
return -ENOSYS;
}
if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
- printk(KERN_DEBUG "rtlx_open channel %d already opened\n",
- index);
+ pr_debug(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
ret = -EBUSY;
goto out_fail;
}
if (rtlx == NULL) {
- if( (p = vpe_get_shared(tclimit)) == NULL) {
- if (can_sleep) {
- __wait_event_interruptible(channel_wqs[index].lx_queue,
- (p = vpe_get_shared(tclimit)), ret);
- if (ret)
+ p = vpe_get_shared(aprp_cpu_index());
+ if (p == NULL) {
+ if (can_sleep) {
+ ret = __wait_event_interruptible(
+ channel_wqs[index].lx_queue,
+ (p = vpe_get_shared(aprp_cpu_index())));
+ if (ret)
+ goto out_fail;
+ } else {
+ pr_debug("No SP program loaded, and device opened with O_NONBLOCK\n");
+ ret = -ENOSYS;
goto out_fail;
- } else {
- printk(KERN_DEBUG "No SP program loaded, and device "
- "opened with O_NONBLOCK\n");
- ret = -ENOSYS;
- goto out_fail;
- }
+ }
}
smp_rmb();
@@ -203,24 +139,24 @@ int rtlx_open(int index, int can_sleep)
ret = -ERESTARTSYS;
goto out_fail;
}
- finish_wait(&channel_wqs[index].lx_queue, &wait);
+ finish_wait(&channel_wqs[index].lx_queue,
+ &wait);
} else {
- pr_err(" *vpe_get_shared is NULL. "
- "Has an SP program been loaded?\n");
+ pr_err(" *vpe_get_shared is NULL. Has an SP program been loaded?\n");
ret = -ENOSYS;
goto out_fail;
}
}
if ((unsigned int)*p < KSEG0) {
- printk(KERN_WARNING "vpe_get_shared returned an "
- "invalid pointer maybe an error code %d\n",
- (int)*p);
+ pr_warn("vpe_get_shared returned an invalid pointer maybe an error code %d\n",
+ (int)*p);
ret = -ENOSYS;
goto out_fail;
}
- if ((ret = rtlx_init(*p)) < 0)
+ ret = rtlx_init(*p);
+ if (ret < 0)
goto out_ret;
}
@@ -263,11 +199,10 @@ unsigned int rtlx_read_poll(int index, int can_sleep)
/* data available to read? */
if (chan->lx_read == chan->lx_write) {
if (can_sleep) {
- int ret = 0;
-
- __wait_event_interruptible(channel_wqs[index].lx_queue,
+ int ret = __wait_event_interruptible(
+ channel_wqs[index].lx_queue,
(chan->lx_read != chan->lx_write) ||
- sp_stopping, ret);
+ sp_stopping);
if (ret)
return ret;
@@ -352,7 +287,7 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count)
size_t fl;
if (rtlx == NULL)
- return(-ENOSYS);
+ return -ENOSYS;
rt = &rtlx->channel[index];
@@ -361,8 +296,8 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count)
rt_read = rt->rt_read;
/* total number of bytes to copy */
- count = min(count, (size_t)write_spacefree(rt_read, rt->rt_write,
- rt->buffer_size));
+ count = min_t(size_t, count, write_spacefree(rt_read, rt->rt_write,
+ rt->buffer_size));
/* first bit from write pointer to the end of the buffer, or count */
fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
@@ -372,9 +307,8 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count)
goto out;
/* if there's any left copy to the beginning of the buffer */
- if (count - fl) {
+ if (count - fl)
failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
- }
out:
count -= failed;
@@ -384,6 +318,8 @@ out:
smp_wmb();
mutex_unlock(&channel_wqs[index].mutex);
+ _interrupt_sp();
+
return count;
}
@@ -398,7 +334,7 @@ static int file_release(struct inode *inode, struct file *filp)
return rtlx_release(iminor(inode));
}
-static unsigned int file_poll(struct file *file, poll_table * wait)
+static unsigned int file_poll(struct file *file, poll_table *wait)
{
int minor = iminor(file_inode(file));
unsigned int mask = 0;
@@ -420,34 +356,32 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
return mask;
}
-static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
- loff_t * ppos)
+static ssize_t file_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *ppos)
{
int minor = iminor(file_inode(file));
/* data available? */
- if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
- return 0; // -EAGAIN makes cat whinge
- }
+ if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1))
+ return 0; /* -EAGAIN makes 'cat' whine */
return rtlx_read(minor, buffer, count);
}
-static ssize_t file_write(struct file *file, const char __user * buffer,
- size_t count, loff_t * ppos)
+static ssize_t file_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
{
int minor = iminor(file_inode(file));
/* any space left... */
if (!rtlx_write_poll(minor)) {
- int ret = 0;
+ int ret;
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
- __wait_event_interruptible(channel_wqs[minor].rt_queue,
- rtlx_write_poll(minor),
- ret);
+ ret = __wait_event_interruptible(channel_wqs[minor].rt_queue,
+ rtlx_write_poll(minor));
if (ret)
return ret;
}
@@ -455,100 +389,16 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
return rtlx_write(minor, buffer, count);
}
-static const struct file_operations rtlx_fops = {
+const struct file_operations rtlx_fops = {
.owner = THIS_MODULE,
- .open = file_open,
+ .open = file_open,
.release = file_release,
.write = file_write,
- .read = file_read,
- .poll = file_poll,
+ .read = file_read,
+ .poll = file_poll,
.llseek = noop_llseek,
};
-static struct irqaction rtlx_irq = {
- .handler = rtlx_interrupt,
- .name = "RTLX",
-};
-
-static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
-
-static char register_chrdev_failed[] __initdata =
- KERN_ERR "rtlx_module_init: unable to register device\n";
-
-static int __init rtlx_module_init(void)
-{
- struct device *dev;
- int i, err;
-
- if (!cpu_has_mipsmt) {
- printk("VPE loader: not a MIPS MT capable processor\n");
- return -ENODEV;
- }
-
- if (tclimit == 0) {
- printk(KERN_WARNING "No TCs reserved for AP/SP, not "
- "initializing RTLX.\nPass maxtcs=<n> argument as kernel "
- "argument\n");
-
- return -ENODEV;
- }
-
- major = register_chrdev(0, module_name, &rtlx_fops);
- if (major < 0) {
- printk(register_chrdev_failed);
- return major;
- }
-
- /* initialise the wait queues */
- for (i = 0; i < RTLX_CHANNELS; i++) {
- init_waitqueue_head(&channel_wqs[i].rt_queue);
- init_waitqueue_head(&channel_wqs[i].lx_queue);
- atomic_set(&channel_wqs[i].in_open, 0);
- mutex_init(&channel_wqs[i].mutex);
-
- dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
- "%s%d", module_name, i);
- if (IS_ERR(dev)) {
- err = PTR_ERR(dev);
- goto out_chrdev;
- }
- }
-
- /* set up notifiers */
- notify.start = starting;
- notify.stop = stopping;
- vpe_notify(tclimit, &notify);
-
- if (cpu_has_vint)
- set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
- else {
- pr_err("APRP RTLX init on non-vectored-interrupt processor\n");
- err = -ENODEV;
- goto out_chrdev;
- }
-
- rtlx_irq.dev_id = rtlx;
- setup_irq(rtlx_irq_num, &rtlx_irq);
-
- return 0;
-
-out_chrdev:
- for (i = 0; i < RTLX_CHANNELS; i++)
- device_destroy(mt_class, MKDEV(major, i));
-
- return err;
-}
-
-static void __exit rtlx_module_exit(void)
-{
- int i;
-
- for (i = 0; i < RTLX_CHANNELS; i++)
- device_destroy(mt_class, MKDEV(major, i));
-
- unregister_chrdev(major, module_name);
-}
-
module_init(rtlx_module_init);
module_exit(rtlx_module_exit);
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index e774bb1088b..3245474f19d 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -6,6 +6,7 @@
* Copyright (C) 1995-99, 2000- 02, 06 Ralf Baechle <ralf@linux-mips.org>
* Copyright (C) 2001 MIPS Technologies, Inc.
* Copyright (C) 2004 Thiemo Seufer
+ * Copyright (C) 2014 Imagination Technologies Ltd.
*/
#include <linux/errno.h>
#include <asm/asm.h>
@@ -40,17 +41,58 @@ NESTED(handle_sys, PT_SIZE, sp)
sw t1, PT_EPC(sp)
beqz t0, illegal_syscall
- sll t0, v0, 3
+ sll t0, v0, 2
la t1, sys_call_table
addu t1, t0
lw t2, (t1) # syscall routine
- lw t3, 4(t1) # >= 0 if we need stack arguments
beqz t2, illegal_syscall
sw a3, PT_R26(sp) # save a3 for syscall restarting
- bgez t3, stackargs
-stack_done:
+ /*
+ * More than four arguments. Try to deal with it by copying the
+ * stack arguments from the user stack to the kernel stack.
+ * This Sucks (TM).
+ */
+ lw t0, PT_R29(sp) # get old user stack pointer
+
+ /*
+ * We intentionally keep the kernel stack a little below the top of
+ * userspace so we don't have to do a slower byte accurate check here.
+ */
+ lw t5, TI_ADDR_LIMIT($28)
+ addu t4, t0, 32
+ and t5, t4
+ bltz t5, bad_stack # -> sp is bad
+
+ /*
+ * Ok, copy the args from the luser stack to the kernel stack.
+ * t3 is the precomputed number of instruction bytes needed to
+ * load or store arguments 6-8.
+ */
+
+ .set push
+ .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
+
+ sw t5, 16(sp) # argument #5 to ksp
+ sw t6, 20(sp) # argument #6 to ksp
+ sw t7, 24(sp) # argument #7 to ksp
+ sw t8, 28(sp) # argument #8 to ksp
+ .set pop
+
+ .section __ex_table,"a"
+ PTR 1b,bad_stack
+ PTR 2b,bad_stack
+ PTR 3b,bad_stack
+ PTR 4b,bad_stack
+ .previous
+
lw t0, TI_FLAGS($28) # syscall tracing enabled?
li t1, _TIF_WORK_SYSCALL_ENTRY
and t0, t1
@@ -77,7 +119,18 @@ syscall_trace_entry:
SAVE_STATIC
move s0, t2
move a0, sp
- jal syscall_trace_enter
+
+ /*
+ * syscall number is in v0 unless we called syscall(__NR_###)
+ * where the real syscall number is in a0
+ */
+ addiu a1, v0, __NR_O32_Linux
+ bnez v0, 1f /* __NR_syscall at offset 0 */
+ lw a1, PT_R4(sp)
+
+1: jal syscall_trace_enter
+
+ bltz v0, 2f # seccomp failed? Skip syscall
move t0, s0
RESTORE_STATIC
@@ -97,71 +150,11 @@ syscall_trace_entry:
sw t1, PT_R0(sp) # save it for syscall restarting
1: sw v0, PT_R2(sp) # result
- j syscall_exit
+2: j syscall_exit
/* ------------------------------------------------------------------------ */
/*
- * More than four arguments. Try to deal with it by copying the
- * stack arguments from the user stack to the kernel stack.
- * This Sucks (TM).
- */
-stackargs:
- lw t0, PT_R29(sp) # get old user stack pointer
-
- /*
- * We intentionally keep the kernel stack a little below the top of
- * userspace so we don't have to do a slower byte accurate check here.
- */
- lw t5, TI_ADDR_LIMIT($28)
- addu t4, t0, 32
- and t5, t4
- bltz t5, bad_stack # -> sp is bad
-
- /* Ok, copy the args from the luser stack to the kernel stack.
- * t3 is the precomputed number of instruction bytes needed to
- * load or store arguments 6-8.
- */
-
- la t1, 5f # load up to 3 arguments
- subu t1, t3
-1: lw t5, 16(t0) # argument #5 from usp
- .set push
- .set noreorder
- .set nomacro
- jr t1
- addiu t1, 6f - 5f
-
-2: lw t8, 28(t0) # argument #8 from usp
-3: lw t7, 24(t0) # argument #7 from usp
-4: lw t6, 20(t0) # argument #6 from usp
-5: jr t1
- sw t5, 16(sp) # argument #5 to ksp
-
-#ifdef CONFIG_CPU_MICROMIPS
- sw t8, 28(sp) # argument #8 to ksp
- nop
- sw t7, 24(sp) # argument #7 to ksp
- nop
- sw t6, 20(sp) # argument #6 to ksp
- nop
-#else
- sw t8, 28(sp) # argument #8 to ksp
- sw t7, 24(sp) # argument #7 to ksp
- sw t6, 20(sp) # argument #6 to ksp
-#endif
-6: j stack_done # go back
- nop
- .set pop
-
- .section __ex_table,"a"
- PTR 1b,bad_stack
- PTR 2b,bad_stack
- PTR 3b,bad_stack
- PTR 4b,bad_stack
- .previous
-
- /*
* The stackpointer for a call with more than 4 arguments is bad.
* We probably should handle this case a bit more drastic.
*/
@@ -187,7 +180,7 @@ illegal_syscall:
subu t0, a0, __NR_O32_Linux # check syscall number
sltiu v0, t0, __NR_O32_Linux_syscalls + 1
beqz t0, einval # do not recurse
- sll t1, t0, 3
+ sll t1, t0, 2
beqz v0, einval
lw t2, sys_call_table(t1) # syscall routine
@@ -218,260 +211,248 @@ einval: li v0, -ENOSYS
jr ra
END(sys_syscall)
- .macro fifty ptr, nargs, from=1, to=50
- sys \ptr \nargs
- .if \to-\from
- fifty \ptr,\nargs,"(\from+1)",\to
- .endif
- .endm
-
- .macro mille ptr, nargs, from=1, to=20
- fifty \ptr,\nargs
- .if \to-\from
- mille \ptr,\nargs,"(\from+1)",\to
- .endif
- .endm
-
- .macro syscalltable
- sys sys_syscall 8 /* 4000 */
- sys sys_exit 1
- sys __sys_fork 0
- sys sys_read 3
- sys sys_write 3
- sys sys_open 3 /* 4005 */
- sys sys_close 1
- sys sys_waitpid 3
- sys sys_creat 2
- sys sys_link 2
- sys sys_unlink 1 /* 4010 */
- sys sys_execve 0
- sys sys_chdir 1
- sys sys_time 1
- sys sys_mknod 3
- sys sys_chmod 2 /* 4015 */
- sys sys_lchown 3
- sys sys_ni_syscall 0
- sys sys_ni_syscall 0 /* was sys_stat */
- sys sys_lseek 3
- sys sys_getpid 0 /* 4020 */
- sys sys_mount 5
- sys sys_oldumount 1
- sys sys_setuid 1
- sys sys_getuid 0
- sys sys_stime 1 /* 4025 */
- sys sys_ptrace 4
- sys sys_alarm 1
- sys sys_ni_syscall 0 /* was sys_fstat */
- sys sys_pause 0
- sys sys_utime 2 /* 4030 */
- sys sys_ni_syscall 0
- sys sys_ni_syscall 0
- sys sys_access 2
- sys sys_nice 1
- sys sys_ni_syscall 0 /* 4035 */
- sys sys_sync 0
- sys sys_kill 2
- sys sys_rename 2
- sys sys_mkdir 2
- sys sys_rmdir 1 /* 4040 */
- sys sys_dup 1
- sys sysm_pipe 0
- sys sys_times 1
- sys sys_ni_syscall 0
- sys sys_brk 1 /* 4045 */
- sys sys_setgid 1
- sys sys_getgid 0
- sys sys_ni_syscall 0 /* was signal(2) */
- sys sys_geteuid 0
- sys sys_getegid 0 /* 4050 */
- sys sys_acct 1
- sys sys_umount 2
- sys sys_ni_syscall 0
- sys sys_ioctl 3
- sys sys_fcntl 3 /* 4055 */
- sys sys_ni_syscall 2
- sys sys_setpgid 2
- sys sys_ni_syscall 0
- sys sys_olduname 1
- sys sys_umask 1 /* 4060 */
- sys sys_chroot 1
- sys sys_ustat 2
- sys sys_dup2 2
- sys sys_getppid 0
- sys sys_getpgrp 0 /* 4065 */
- sys sys_setsid 0
- sys sys_sigaction 3
- sys sys_sgetmask 0
- sys sys_ssetmask 1
- sys sys_setreuid 2 /* 4070 */
- sys sys_setregid 2
- sys sys_sigsuspend 0
- sys sys_sigpending 1
- sys sys_sethostname 2
- sys sys_setrlimit 2 /* 4075 */
- sys sys_getrlimit 2
- sys sys_getrusage 2
- sys sys_gettimeofday 2
- sys sys_settimeofday 2
- sys sys_getgroups 2 /* 4080 */
- sys sys_setgroups 2
- sys sys_ni_syscall 0 /* old_select */
- sys sys_symlink 2
- sys sys_ni_syscall 0 /* was sys_lstat */
- sys sys_readlink 3 /* 4085 */
- sys sys_uselib 1
- sys sys_swapon 2
- sys sys_reboot 3
- sys sys_old_readdir 3
- sys sys_mips_mmap 6 /* 4090 */
- sys sys_munmap 2
- sys sys_truncate 2
- sys sys_ftruncate 2
- sys sys_fchmod 2
- sys sys_fchown 3 /* 4095 */
- sys sys_getpriority 2
- sys sys_setpriority 3
- sys sys_ni_syscall 0
- sys sys_statfs 2
- sys sys_fstatfs 2 /* 4100 */
- sys sys_ni_syscall 0 /* was ioperm(2) */
- sys sys_socketcall 2
- sys sys_syslog 3
- sys sys_setitimer 3
- sys sys_getitimer 2 /* 4105 */
- sys sys_newstat 2
- sys sys_newlstat 2
- sys sys_newfstat 2
- sys sys_uname 1
- sys sys_ni_syscall 0 /* 4110 was iopl(2) */
- sys sys_vhangup 0
- sys sys_ni_syscall 0 /* was sys_idle() */
- sys sys_ni_syscall 0 /* was sys_vm86 */
- sys sys_wait4 4
- sys sys_swapoff 1 /* 4115 */
- sys sys_sysinfo 1
- sys sys_ipc 6
- sys sys_fsync 1
- sys sys_sigreturn 0
- sys __sys_clone 6 /* 4120 */
- sys sys_setdomainname 2
- sys sys_newuname 1
- sys sys_ni_syscall 0 /* sys_modify_ldt */
- sys sys_adjtimex 1
- sys sys_mprotect 3 /* 4125 */
- sys sys_sigprocmask 3
- sys sys_ni_syscall 0 /* was create_module */
- sys sys_init_module 5
- sys sys_delete_module 1
- sys sys_ni_syscall 0 /* 4130 was get_kernel_syms */
- sys sys_quotactl 4
- sys sys_getpgid 1
- sys sys_fchdir 1
- sys sys_bdflush 2
- sys sys_sysfs 3 /* 4135 */
- sys sys_personality 1
- sys sys_ni_syscall 0 /* for afs_syscall */
- sys sys_setfsuid 1
- sys sys_setfsgid 1
- sys sys_llseek 5 /* 4140 */
- sys sys_getdents 3
- sys sys_select 5
- sys sys_flock 2
- sys sys_msync 3
- sys sys_readv 3 /* 4145 */
- sys sys_writev 3
- sys sys_cacheflush 3
- sys sys_cachectl 3
- sys sys_sysmips 4
- sys sys_ni_syscall 0 /* 4150 */
- sys sys_getsid 1
- sys sys_fdatasync 1
- sys sys_sysctl 1
- sys sys_mlock 2
- sys sys_munlock 2 /* 4155 */
- sys sys_mlockall 1
- sys sys_munlockall 0
- sys sys_sched_setparam 2
- sys sys_sched_getparam 2
- sys sys_sched_setscheduler 3 /* 4160 */
- sys sys_sched_getscheduler 1
- sys sys_sched_yield 0
- sys sys_sched_get_priority_max 1
- sys sys_sched_get_priority_min 1
- sys sys_sched_rr_get_interval 2 /* 4165 */
- sys sys_nanosleep, 2
- sys sys_mremap, 5
- sys sys_accept 3
- sys sys_bind 3
- sys sys_connect 3 /* 4170 */
- sys sys_getpeername 3
- sys sys_getsockname 3
- sys sys_getsockopt 5
- sys sys_listen 2
- sys sys_recv 4 /* 4175 */
- sys sys_recvfrom 6
- sys sys_recvmsg 3
- sys sys_send 4
- sys sys_sendmsg 3
- sys sys_sendto 6 /* 4180 */
- sys sys_setsockopt 5
- sys sys_shutdown 2
- sys sys_socket 3
- sys sys_socketpair 4
- sys sys_setresuid 3 /* 4185 */
- sys sys_getresuid 3
- sys sys_ni_syscall 0 /* was sys_query_module */
- sys sys_poll 3
- sys sys_ni_syscall 0 /* was nfsservctl */
- sys sys_setresgid 3 /* 4190 */
- sys sys_getresgid 3
- sys sys_prctl 5
- sys sys_rt_sigreturn 0
- sys sys_rt_sigaction 4
- sys sys_rt_sigprocmask 4 /* 4195 */
- sys sys_rt_sigpending 2
- sys sys_rt_sigtimedwait 4
- sys sys_rt_sigqueueinfo 3
- sys sys_rt_sigsuspend 0
- sys sys_pread64 6 /* 4200 */
- sys sys_pwrite64 6
- sys sys_chown 3
- sys sys_getcwd 2
- sys sys_capget 2
- sys sys_capset 2 /* 4205 */
- sys sys_sigaltstack 0
- sys sys_sendfile 4
- sys sys_ni_syscall 0
- sys sys_ni_syscall 0
- sys sys_mips_mmap2 6 /* 4210 */
- sys sys_truncate64 4
- sys sys_ftruncate64 4
- sys sys_stat64 2
- sys sys_lstat64 2
- sys sys_fstat64 2 /* 4215 */
- sys sys_pivot_root 2
- sys sys_mincore 3
- sys sys_madvise 3
- sys sys_getdents64 3
- sys sys_fcntl64 3 /* 4220 */
- sys sys_ni_syscall 0
- sys sys_gettid 0
- sys sys_readahead 5
- sys sys_setxattr 5
- sys sys_lsetxattr 5 /* 4225 */
- sys sys_fsetxattr 5
- sys sys_getxattr 4
- sys sys_lgetxattr 4
- sys sys_fgetxattr 4
- sys sys_listxattr 3 /* 4230 */
- sys sys_llistxattr 3
- sys sys_flistxattr 3
- sys sys_removexattr 2
- sys sys_lremovexattr 2
- sys sys_fremovexattr 2 /* 4235 */
- sys sys_tkill 2
- sys sys_sendfile64 5
- sys sys_futex 6
+ .align 2
+ .type sys_call_table, @object
+EXPORT(sys_call_table)
+ PTR sys_syscall /* 4000 */
+ PTR sys_exit
+ PTR __sys_fork
+ PTR sys_read
+ PTR sys_write
+ PTR sys_open /* 4005 */
+ PTR sys_close
+ PTR sys_waitpid
+ PTR sys_creat
+ PTR sys_link
+ PTR sys_unlink /* 4010 */
+ PTR sys_execve
+ PTR sys_chdir
+ PTR sys_time
+ PTR sys_mknod
+ PTR sys_chmod /* 4015 */
+ PTR sys_lchown
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall /* was sys_stat */
+ PTR sys_lseek
+ PTR sys_getpid /* 4020 */
+ PTR sys_mount
+ PTR sys_oldumount
+ PTR sys_setuid
+ PTR sys_getuid
+ PTR sys_stime /* 4025 */
+ PTR sys_ptrace
+ PTR sys_alarm
+ PTR sys_ni_syscall /* was sys_fstat */
+ PTR sys_pause
+ PTR sys_utime /* 4030 */
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+ PTR sys_access
+ PTR sys_nice
+ PTR sys_ni_syscall /* 4035 */
+ PTR sys_sync
+ PTR sys_kill
+ PTR sys_rename
+ PTR sys_mkdir
+ PTR sys_rmdir /* 4040 */
+ PTR sys_dup
+ PTR sysm_pipe
+ PTR sys_times
+ PTR sys_ni_syscall
+ PTR sys_brk /* 4045 */
+ PTR sys_setgid
+ PTR sys_getgid
+ PTR sys_ni_syscall /* was signal(2) */
+ PTR sys_geteuid
+ PTR sys_getegid /* 4050 */
+ PTR sys_acct
+ PTR sys_umount
+ PTR sys_ni_syscall
+ PTR sys_ioctl
+ PTR sys_fcntl /* 4055 */
+ PTR sys_ni_syscall
+ PTR sys_setpgid
+ PTR sys_ni_syscall
+ PTR sys_olduname
+ PTR sys_umask /* 4060 */
+ PTR sys_chroot
+ PTR sys_ustat
+ PTR sys_dup2
+ PTR sys_getppid
+ PTR sys_getpgrp /* 4065 */
+ PTR sys_setsid
+ PTR sys_sigaction
+ PTR sys_sgetmask
+ PTR sys_ssetmask
+ PTR sys_setreuid /* 4070 */
+ PTR sys_setregid
+ PTR sys_sigsuspend
+ PTR sys_sigpending
+ PTR sys_sethostname
+ PTR sys_setrlimit /* 4075 */
+ PTR sys_getrlimit
+ PTR sys_getrusage
+ PTR sys_gettimeofday
+ PTR sys_settimeofday
+ PTR sys_getgroups /* 4080 */
+ PTR sys_setgroups
+ PTR sys_ni_syscall /* old_select */
+ PTR sys_symlink
+ PTR sys_ni_syscall /* was sys_lstat */
+ PTR sys_readlink /* 4085 */
+ PTR sys_uselib
+ PTR sys_swapon
+ PTR sys_reboot
+ PTR sys_old_readdir
+ PTR sys_mips_mmap /* 4090 */
+ PTR sys_munmap
+ PTR sys_truncate
+ PTR sys_ftruncate
+ PTR sys_fchmod
+ PTR sys_fchown /* 4095 */
+ PTR sys_getpriority
+ PTR sys_setpriority
+ PTR sys_ni_syscall
+ PTR sys_statfs
+ PTR sys_fstatfs /* 4100 */
+ PTR sys_ni_syscall /* was ioperm(2) */
+ PTR sys_socketcall
+ PTR sys_syslog
+ PTR sys_setitimer
+ PTR sys_getitimer /* 4105 */
+ PTR sys_newstat
+ PTR sys_newlstat
+ PTR sys_newfstat
+ PTR sys_uname
+ PTR sys_ni_syscall /* 4110 was iopl(2) */
+ PTR sys_vhangup
+ PTR sys_ni_syscall /* was sys_idle() */
+ PTR sys_ni_syscall /* was sys_vm86 */
+ PTR sys_wait4
+ PTR sys_swapoff /* 4115 */
+ PTR sys_sysinfo
+ PTR sys_ipc
+ PTR sys_fsync
+ PTR sys_sigreturn
+ PTR __sys_clone /* 4120 */
+ PTR sys_setdomainname
+ PTR sys_newuname
+ PTR sys_ni_syscall /* sys_modify_ldt */
+ PTR sys_adjtimex
+ PTR sys_mprotect /* 4125 */
+ PTR sys_sigprocmask
+ PTR sys_ni_syscall /* was create_module */
+ PTR sys_init_module
+ PTR sys_delete_module
+ PTR sys_ni_syscall /* 4130 was get_kernel_syms */
+ PTR sys_quotactl
+ PTR sys_getpgid
+ PTR sys_fchdir
+ PTR sys_bdflush
+ PTR sys_sysfs /* 4135 */
+ PTR sys_personality
+ PTR sys_ni_syscall /* for afs_syscall */
+ PTR sys_setfsuid
+ PTR sys_setfsgid
+ PTR sys_llseek /* 4140 */
+ PTR sys_getdents
+ PTR sys_select
+ PTR sys_flock
+ PTR sys_msync
+ PTR sys_readv /* 4145 */
+ PTR sys_writev
+ PTR sys_cacheflush
+ PTR sys_cachectl
+ PTR sys_sysmips
+ PTR sys_ni_syscall /* 4150 */
+ PTR sys_getsid
+ PTR sys_fdatasync
+ PTR sys_sysctl
+ PTR sys_mlock
+ PTR sys_munlock /* 4155 */
+ PTR sys_mlockall
+ PTR sys_munlockall
+ PTR sys_sched_setparam
+ PTR sys_sched_getparam
+ PTR sys_sched_setscheduler /* 4160 */
+ PTR sys_sched_getscheduler
+ PTR sys_sched_yield
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+ PTR sys_sched_rr_get_interval /* 4165 */
+ PTR sys_nanosleep
+ PTR sys_mremap
+ PTR sys_accept
+ PTR sys_bind
+ PTR sys_connect /* 4170 */
+ PTR sys_getpeername
+ PTR sys_getsockname
+ PTR sys_getsockopt
+ PTR sys_listen
+ PTR sys_recv /* 4175 */
+ PTR sys_recvfrom
+ PTR sys_recvmsg
+ PTR sys_send
+ PTR sys_sendmsg
+ PTR sys_sendto /* 4180 */
+ PTR sys_setsockopt
+ PTR sys_shutdown
+ PTR sys_socket
+ PTR sys_socketpair
+ PTR sys_setresuid /* 4185 */
+ PTR sys_getresuid
+ PTR sys_ni_syscall /* was sys_query_module */
+ PTR sys_poll
+ PTR sys_ni_syscall /* was nfsservctl */
+ PTR sys_setresgid /* 4190 */
+ PTR sys_getresgid
+ PTR sys_prctl
+ PTR sys_rt_sigreturn
+ PTR sys_rt_sigaction
+ PTR sys_rt_sigprocmask /* 4195 */
+ PTR sys_rt_sigpending
+ PTR sys_rt_sigtimedwait
+ PTR sys_rt_sigqueueinfo
+ PTR sys_rt_sigsuspend
+ PTR sys_pread64 /* 4200 */
+ PTR sys_pwrite64
+ PTR sys_chown
+ PTR sys_getcwd
+ PTR sys_capget
+ PTR sys_capset /* 4205 */
+ PTR sys_sigaltstack
+ PTR sys_sendfile
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+ PTR sys_mips_mmap2 /* 4210 */
+ PTR sys_truncate64
+ PTR sys_ftruncate64
+ PTR sys_stat64
+ PTR sys_lstat64
+ PTR sys_fstat64 /* 4215 */
+ PTR sys_pivot_root
+ PTR sys_mincore
+ PTR sys_madvise
+ PTR sys_getdents64
+ PTR sys_fcntl64 /* 4220 */
+ PTR sys_ni_syscall
+ PTR sys_gettid
+ PTR sys_readahead
+ PTR sys_setxattr
+ PTR sys_lsetxattr /* 4225 */
+ PTR sys_fsetxattr
+ PTR sys_getxattr
+ PTR sys_lgetxattr
+ PTR sys_fgetxattr
+ PTR sys_listxattr /* 4230 */
+ PTR sys_llistxattr
+ PTR sys_flistxattr
+ PTR sys_removexattr
+ PTR sys_lremovexattr
+ PTR sys_fremovexattr /* 4235 */
+ PTR sys_tkill
+ PTR sys_sendfile64
+ PTR sys_futex
#ifdef CONFIG_MIPS_MT_FPAFF
/*
* For FPU affinity scheduling on MIPS MT processors, we need to
@@ -480,132 +461,120 @@ einval: li v0, -ENOSYS
* these hooks for the 32-bit kernel - there is no MIPS64 MT processor
* atm.
*/
- sys mipsmt_sys_sched_setaffinity 3
- sys mipsmt_sys_sched_getaffinity 3
+ PTR mipsmt_sys_sched_setaffinity
+ PTR mipsmt_sys_sched_getaffinity
#else
- sys sys_sched_setaffinity 3
- sys sys_sched_getaffinity 3 /* 4240 */
+ PTR sys_sched_setaffinity
+ PTR sys_sched_getaffinity /* 4240 */
#endif /* CONFIG_MIPS_MT_FPAFF */
- sys sys_io_setup 2
- sys sys_io_destroy 1
- sys sys_io_getevents 5
- sys sys_io_submit 3
- sys sys_io_cancel 3 /* 4245 */
- sys sys_exit_group 1
- sys sys_lookup_dcookie 4
- sys sys_epoll_create 1
- sys sys_epoll_ctl 4
- sys sys_epoll_wait 4 /* 4250 */
- sys sys_remap_file_pages 5
- sys sys_set_tid_address 1
- sys sys_restart_syscall 0
- sys sys_fadvise64_64 7
- sys sys_statfs64 3 /* 4255 */
- sys sys_fstatfs64 2
- sys sys_timer_create 3
- sys sys_timer_settime 4
- sys sys_timer_gettime 2
- sys sys_timer_getoverrun 1 /* 4260 */
- sys sys_timer_delete 1
- sys sys_clock_settime 2
- sys sys_clock_gettime 2
- sys sys_clock_getres 2
- sys sys_clock_nanosleep 4 /* 4265 */
- sys sys_tgkill 3
- sys sys_utimes 2
- sys sys_mbind 4
- sys sys_ni_syscall 0 /* sys_get_mempolicy */
- sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */
- sys sys_mq_open 4
- sys sys_mq_unlink 1
- sys sys_mq_timedsend 5
- sys sys_mq_timedreceive 5
- sys sys_mq_notify 2 /* 4275 */
- sys sys_mq_getsetattr 3
- sys sys_ni_syscall 0 /* sys_vserver */
- sys sys_waitid 5
- sys sys_ni_syscall 0 /* available, was setaltroot */
- sys sys_add_key 5 /* 4280 */
- sys sys_request_key 4
- sys sys_keyctl 5
- sys sys_set_thread_area 1
- sys sys_inotify_init 0
- sys sys_inotify_add_watch 3 /* 4285 */
- sys sys_inotify_rm_watch 2
- sys sys_migrate_pages 4
- sys sys_openat 4
- sys sys_mkdirat 3
- sys sys_mknodat 4 /* 4290 */
- sys sys_fchownat 5
- sys sys_futimesat 3
- sys sys_fstatat64 4
- sys sys_unlinkat 3
- sys sys_renameat 4 /* 4295 */
- sys sys_linkat 5
- sys sys_symlinkat 3
- sys sys_readlinkat 4
- sys sys_fchmodat 3
- sys sys_faccessat 3 /* 4300 */
- sys sys_pselect6 6
- sys sys_ppoll 5
- sys sys_unshare 1
- sys sys_splice 6
- sys sys_sync_file_range 7 /* 4305 */
- sys sys_tee 4
- sys sys_vmsplice 4
- sys sys_move_pages 6
- sys sys_set_robust_list 2
- sys sys_get_robust_list 3 /* 4310 */
- sys sys_kexec_load 4
- sys sys_getcpu 3
- sys sys_epoll_pwait 6
- sys sys_ioprio_set 3
- sys sys_ioprio_get 2 /* 4315 */
- sys sys_utimensat 4
- sys sys_signalfd 3
- sys sys_ni_syscall 0 /* was timerfd */
- sys sys_eventfd 1
- sys sys_fallocate 6 /* 4320 */
- sys sys_timerfd_create 2
- sys sys_timerfd_gettime 2
- sys sys_timerfd_settime 4
- sys sys_signalfd4 4
- sys sys_eventfd2 2 /* 4325 */
- sys sys_epoll_create1 1
- sys sys_dup3 3
- sys sys_pipe2 2
- sys sys_inotify_init1 1
- sys sys_preadv 6 /* 4330 */
- sys sys_pwritev 6
- sys sys_rt_tgsigqueueinfo 4
- sys sys_perf_event_open 5
- sys sys_accept4 4
- sys sys_recvmmsg 5 /* 4335 */
- sys sys_fanotify_init 2
- sys sys_fanotify_mark 6
- sys sys_prlimit64 4
- sys sys_name_to_handle_at 5
- sys sys_open_by_handle_at 3 /* 4340 */
- sys sys_clock_adjtime 2
- sys sys_syncfs 1
- sys sys_sendmmsg 4
- sys sys_setns 2
- sys sys_process_vm_readv 6 /* 4345 */
- sys sys_process_vm_writev 6
- sys sys_kcmp 5
- sys sys_finit_module 3
- .endm
-
- /* We pre-compute the number of _instruction_ bytes needed to
- load or store the arguments 6-8. Negative values are ignored. */
-
- .macro sys function, nargs
- PTR \function
- LONG (\nargs << 2) - (5 << 2)
- .endm
-
- .align 3
- .type sys_call_table,@object
-EXPORT(sys_call_table)
- syscalltable
- .size sys_call_table, . - sys_call_table
+ PTR sys_io_setup
+ PTR sys_io_destroy
+ PTR sys_io_getevents
+ PTR sys_io_submit
+ PTR sys_io_cancel /* 4245 */
+ PTR sys_exit_group
+ PTR sys_lookup_dcookie
+ PTR sys_epoll_create
+ PTR sys_epoll_ctl
+ PTR sys_epoll_wait /* 4250 */
+ PTR sys_remap_file_pages
+ PTR sys_set_tid_address
+ PTR sys_restart_syscall
+ PTR sys_fadvise64_64
+ PTR sys_statfs64 /* 4255 */
+ PTR sys_fstatfs64
+ PTR sys_timer_create
+ PTR sys_timer_settime
+ PTR sys_timer_gettime
+ PTR sys_timer_getoverrun /* 4260 */
+ PTR sys_timer_delete
+ PTR sys_clock_settime
+ PTR sys_clock_gettime
+ PTR sys_clock_getres
+ PTR sys_clock_nanosleep /* 4265 */
+ PTR sys_tgkill
+ PTR sys_utimes
+ PTR sys_mbind
+ PTR sys_ni_syscall /* sys_get_mempolicy */
+ PTR sys_ni_syscall /* 4270 sys_set_mempolicy */
+ PTR sys_mq_open
+ PTR sys_mq_unlink
+ PTR sys_mq_timedsend
+ PTR sys_mq_timedreceive
+ PTR sys_mq_notify /* 4275 */
+ PTR sys_mq_getsetattr
+ PTR sys_ni_syscall /* sys_vserver */
+ PTR sys_waitid
+ PTR sys_ni_syscall /* available, was setaltroot */
+ PTR sys_add_key /* 4280 */
+ PTR sys_request_key
+ PTR sys_keyctl
+ PTR sys_set_thread_area
+ PTR sys_inotify_init
+ PTR sys_inotify_add_watch /* 4285 */
+ PTR sys_inotify_rm_watch
+ PTR sys_migrate_pages
+ PTR sys_openat
+ PTR sys_mkdirat
+ PTR sys_mknodat /* 4290 */
+ PTR sys_fchownat
+ PTR sys_futimesat
+ PTR sys_fstatat64
+ PTR sys_unlinkat
+ PTR sys_renameat /* 4295 */
+ PTR sys_linkat
+ PTR sys_symlinkat
+ PTR sys_readlinkat
+ PTR sys_fchmodat
+ PTR sys_faccessat /* 4300 */
+ PTR sys_pselect6
+ PTR sys_ppoll
+ PTR sys_unshare
+ PTR sys_splice
+ PTR sys_sync_file_range /* 4305 */
+ PTR sys_tee
+ PTR sys_vmsplice
+ PTR sys_move_pages
+ PTR sys_set_robust_list
+ PTR sys_get_robust_list /* 4310 */
+ PTR sys_kexec_load
+ PTR sys_getcpu
+ PTR sys_epoll_pwait
+ PTR sys_ioprio_set
+ PTR sys_ioprio_get /* 4315 */
+ PTR sys_utimensat
+ PTR sys_signalfd
+ PTR sys_ni_syscall /* was timerfd */
+ PTR sys_eventfd
+ PTR sys_fallocate /* 4320 */
+ PTR sys_timerfd_create
+ PTR sys_timerfd_gettime
+ PTR sys_timerfd_settime
+ PTR sys_signalfd4
+ PTR sys_eventfd2 /* 4325 */
+ PTR sys_epoll_create1
+ PTR sys_dup3
+ PTR sys_pipe2
+ PTR sys_inotify_init1
+ PTR sys_preadv /* 4330 */
+ PTR sys_pwritev
+ PTR sys_rt_tgsigqueueinfo
+ PTR sys_perf_event_open
+ PTR sys_accept4
+ PTR sys_recvmmsg /* 4335 */
+ PTR sys_fanotify_init
+ PTR sys_fanotify_mark
+ PTR sys_prlimit64
+ PTR sys_name_to_handle_at
+ PTR sys_open_by_handle_at /* 4340 */
+ PTR sys_clock_adjtime
+ PTR sys_syncfs
+ PTR sys_sendmmsg
+ PTR sys_setns
+ PTR sys_process_vm_readv /* 4345 */
+ PTR sys_process_vm_writev
+ PTR sys_kcmp
+ PTR sys_finit_module
+ PTR sys_sched_setattr
+ PTR sys_sched_getattr /* 4350 */
+ PTR sys_renameat2
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index be6627ead61..be2fedd4ae3 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -80,8 +80,11 @@ syscall_trace_entry:
SAVE_STATIC
move s0, t2
move a0, sp
+ daddiu a1, v0, __NR_64_Linux
jal syscall_trace_enter
+ bltz v0, 2f # seccomp failed? Skip syscall
+
move t0, s0
RESTORE_STATIC
ld a0, PT_R4(sp) # Restore argument registers
@@ -102,7 +105,7 @@ syscall_trace_entry:
sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
- j syscall_exit
+2: j syscall_exit
illegal_syscall:
/* This also isn't a 64-bit syscall, throw an error. */
@@ -114,7 +117,8 @@ illegal_syscall:
END(handle_sys64)
.align 3
-sys_call_table:
+ .type sys_call_table, @object
+EXPORT(sys_call_table)
PTR sys_read /* 5000 */
PTR sys_write
PTR sys_open
@@ -424,4 +428,7 @@ sys_call_table:
PTR sys_kcmp
PTR sys_finit_module
PTR sys_getdents64
+ PTR sys_sched_setattr
+ PTR sys_sched_getattr /* 5310 */
+ PTR sys_renameat2
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index cab150789c8..c1dbcda4b81 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -72,8 +72,11 @@ n32_syscall_trace_entry:
SAVE_STATIC
move s0, t2
move a0, sp
+ daddiu a1, v0, __NR_N32_Linux
jal syscall_trace_enter
+ bltz v0, 2f # seccomp failed? Skip syscall
+
move t0, s0
RESTORE_STATIC
ld a0, PT_R4(sp) # Restore argument registers
@@ -94,7 +97,7 @@ n32_syscall_trace_entry:
sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
- j syscall_exit
+2: j syscall_exit
not_n32_scall:
/* This is not an n32 compatibility syscall, pass it on to
@@ -103,6 +106,7 @@ not_n32_scall:
END(handle_sysn32)
+ .type sysn32_call_table, @object
EXPORT(sysn32_call_table)
PTR sys_read /* 6000 */
PTR sys_write
@@ -417,4 +421,7 @@ EXPORT(sysn32_call_table)
PTR compat_sys_process_vm_writev /* 6310 */
PTR sys_kcmp
PTR sys_finit_module
+ PTR sys_sched_setattr
+ PTR sys_sched_getattr
+ PTR sys_renameat2 /* 6315 */
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 37605dc8eef..f1343ccd7ed 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -53,7 +53,7 @@ NESTED(handle_sys, PT_SIZE, sp)
sll a3, a3, 0
dsll t0, v0, 3 # offset into table
- ld t2, (sys_call_table - (__NR_O32_Linux * 8))(t0)
+ ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
sd a3, PT_R26(sp) # save a3 for syscall restarting
@@ -112,7 +112,20 @@ trace_a_syscall:
move s0, t2 # Save syscall pointer
move a0, sp
- jal syscall_trace_enter
+ /*
+ * syscall number is in v0 unless we called syscall(__NR_###)
+ * where the real syscall number is in a0
+ * note: NR_syscall is the first O32 syscall but the macro is
+ * only defined when compiling with -mabi=32 (CONFIG_32BIT)
+ * therefore __NR_O32_Linux is used (4000)
+ */
+ addiu a1, v0, __NR_O32_Linux
+ bnez v0, 1f /* __NR_syscall at offset 0 */
+ lw a1, PT_R4(sp)
+
+1: jal syscall_trace_enter
+
+ bltz v0, 2f # seccomp failed? Skip syscall
move t0, s0
RESTORE_STATIC
@@ -136,7 +149,7 @@ trace_a_syscall:
sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
- j syscall_exit
+2: j syscall_exit
/* ------------------------------------------------------------------------ */
@@ -168,7 +181,7 @@ LEAF(sys32_syscall)
beqz t0, einval # do not recurse
dsll t1, t0, 3
beqz v0, einval
- ld t2, sys_call_table(t1) # syscall routine
+ ld t2, sys32_call_table(t1) # syscall routine
move a0, a1 # shift argument registers
move a1, a2
@@ -190,8 +203,8 @@ einval: li v0, -ENOSYS
END(sys32_syscall)
.align 3
- .type sys_call_table,@object
-sys_call_table:
+ .type sys32_call_table,@object
+EXPORT(sys32_call_table)
PTR sys32_syscall /* 4000 */
PTR sys_exit
PTR __sys_fork
@@ -541,4 +554,7 @@ sys_call_table:
PTR compat_sys_process_vm_writev
PTR sys_kcmp
PTR sys_finit_module
- .size sys_call_table,.-sys_call_table
+ PTR sys_sched_setattr
+ PTR sys_sched_getattr /* 4350 */
+ PTR sys_renameat2
+ .size sys32_call_table,.-sys32_call_table
diff --git a/arch/mips/kernel/segment.c b/arch/mips/kernel/segment.c
new file mode 100644
index 00000000000..076ead2a985
--- /dev/null
+++ b/arch/mips/kernel/segment.c
@@ -0,0 +1,110 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ */
+
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+static void build_segment_config(char *str, unsigned int cfg)
+{
+ unsigned int am;
+ static const char * const am_str[] = {
+ "UK", "MK", "MSK", "MUSK", "MUSUK", "USK",
+ "RSRVD", "UUSK"};
+
+ /* Segment access mode. */
+ am = (cfg & MIPS_SEGCFG_AM) >> MIPS_SEGCFG_AM_SHIFT;
+ str += sprintf(str, "%-5s", am_str[am]);
+
+ /*
+ * Access modes MK, MSK and MUSK are mapped segments. Therefore
+ * there is no direct physical address mapping.
+ */
+ if ((am == 0) || (am > 3)) {
+ str += sprintf(str, " %03lx",
+ ((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT));
+ str += sprintf(str, " %01ld",
+ ((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT));
+ } else {
+ str += sprintf(str, " UND");
+ str += sprintf(str, " U");
+ }
+
+ /* Exception configuration. */
+ str += sprintf(str, " %01ld\n",
+ ((cfg & MIPS_SEGCFG_EU) >> MIPS_SEGCFG_EU_SHIFT));
+}
+
+static int show_segments(struct seq_file *m, void *v)
+{
+ unsigned int segcfg;
+ char str[42];
+
+ seq_puts(m, "Segment Virtual Size Access Mode Physical Caching EU\n");
+ seq_puts(m, "------- ------- ---- ----------- -------- ------- --\n");
+
+ segcfg = read_c0_segctl0();
+ build_segment_config(str, segcfg);
+ seq_printf(m, " 0 e0000000 512M %s", str);
+
+ segcfg >>= 16;
+ build_segment_config(str, segcfg);
+ seq_printf(m, " 1 c0000000 512M %s", str);
+
+ segcfg = read_c0_segctl1();
+ build_segment_config(str, segcfg);
+ seq_printf(m, " 2 a0000000 512M %s", str);
+
+ segcfg >>= 16;
+ build_segment_config(str, segcfg);
+ seq_printf(m, " 3 80000000 512M %s", str);
+
+ segcfg = read_c0_segctl2();
+ build_segment_config(str, segcfg);
+ seq_printf(m, " 4 40000000 1G %s", str);
+
+ segcfg >>= 16;
+ build_segment_config(str, segcfg);
+ seq_printf(m, " 5 00000000 1G %s\n", str);
+
+ return 0;
+}
+
+static int segments_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, show_segments, NULL);
+}
+
+static const struct file_operations segments_fops = {
+ .open = segments_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init segments_info(void)
+{
+ extern struct dentry *mips_debugfs_dir;
+ struct dentry *segments;
+
+ if (cpu_has_segments) {
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+
+ segments = debugfs_create_file("segments", S_IRUGO,
+ mips_debugfs_dir, NULL,
+ &segments_fops);
+ if (!segments)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+device_initcall(segments_info);
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index c538d6e01b7..a842154d57d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -300,12 +300,13 @@ static void __init bootmem_init(void)
int i;
/*
- * Init any data related to initrd. It's a nop if INITRD is
- * not selected. Once that done we can determine the low bound
- * of usable memory.
+ * Sanity check any INITRD first. We don't take it into account
+ * for bootmem setup initially, rely on the end-of-kernel-code
+ * as our memory range starting point. Once bootmem is inited we
+ * will reserve the area used for the initrd.
*/
- reserved_end = max(init_initrd(),
- (unsigned long) PFN_UP(__pa_symbol(&_end)));
+ init_initrd();
+ reserved_end = (unsigned long) PFN_UP(__pa_symbol(&_end));
/*
* max_low_pfn is not a number of pages. The number of pages
@@ -362,6 +363,14 @@ static void __init bootmem_init(void)
max_low_pfn = PFN_DOWN(HIGHMEM_START);
}
+#ifdef CONFIG_BLK_DEV_INITRD
+ /*
+ * mapstart should be after initrd_end
+ */
+ if (initrd_end)
+ mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end)));
+#endif
+
/*
* Initialize the boot-time allocator with low memory only.
*/
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 2f285abc76d..9e60d117e41 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -6,6 +6,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994 - 2000 Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2014, Imagination Technologies Ltd.
*/
#include <linux/cache.h>
#include <linux/context_tracking.h>
@@ -46,9 +47,6 @@ 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);
-extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
-extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
-
struct sigframe {
u32 sf_ass[4]; /* argument save space for o32 */
u32 sf_pad[2]; /* Was: signal trampoline */
@@ -64,16 +62,55 @@ 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)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ 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_sigcontext(struct sigcontext __user *sc)
+{
+ int i;
+ int err = 0;
+ u64 fpr_val;
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ 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;
+}
+
+/*
* Helper routines
*/
static int protected_save_fp_context(struct sigcontext __user *sc)
{
int err;
+#ifndef CONFIG_EVA
while (1) {
lock_fpu_owner();
- own_fpu_inatomic(1);
- err = save_fp_context(sc); /* this might fail */
- unlock_fpu_owner();
+ if (is_fpu_owner()) {
+ err = save_fp_context(sc);
+ unlock_fpu_owner();
+ } else {
+ unlock_fpu_owner();
+ err = copy_fp_to_sigcontext(sc);
+ }
if (likely(!err))
break;
/* touch the sigcontext and try again */
@@ -83,17 +120,30 @@ static int protected_save_fp_context(struct sigcontext __user *sc)
if (err)
break; /* 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;
}
static int protected_restore_fp_context(struct sigcontext __user *sc)
{
int err, tmp __maybe_unused;
+#ifndef CONFIG_EVA
while (1) {
lock_fpu_owner();
- own_fpu_inatomic(0);
- err = restore_fp_context(sc); /* this might fail */
- unlock_fpu_owner();
+ if (is_fpu_owner()) {
+ err = restore_fp_context(sc);
+ unlock_fpu_owner();
+ } else {
+ unlock_fpu_owner();
+ err = copy_fp_from_sigcontext(sc);
+ }
if (likely(!err))
break;
/* touch the sigcontext and try again */
@@ -103,6 +153,14 @@ static int protected_restore_fp_context(struct sigcontext __user *sc)
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;
}
@@ -589,23 +647,26 @@ 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)
{
return raw_cpu_has_fpu
? _save_fp_context(sc)
- : fpu_emulator_save_context(sc);
+ : copy_fp_to_sigcontext(sc);
}
static int smp_restore_fp_context(struct sigcontext __user *sc)
{
return raw_cpu_has_fpu
? _restore_fp_context(sc)
- : fpu_emulator_restore_context(sc);
+ : copy_fp_from_sigcontext(sc);
}
+#endif /* CONFIG_EVA */
#endif
static int signal_setup(void)
{
+#ifndef CONFIG_EVA
#ifdef CONFIG_SMP
/* For now just do the cpu_has_fpu check when the functions are invoked */
save_fp_context = smp_save_fp_context;
@@ -615,9 +676,13 @@ static int signal_setup(void)
save_fp_context = _save_fp_context;
restore_fp_context = _restore_fp_context;
} else {
- save_fp_context = fpu_emulator_save_context;
- restore_fp_context = fpu_emulator_restore_context;
+ save_fp_context = copy_fp_from_sigcontext;
+ restore_fp_context = copy_fp_to_sigcontext;
}
+#endif /* CONFIG_SMP */
+#else
+ save_fp_context = copy_fp_from_sigcontext;;
+ restore_fp_context = copy_fp_to_sigcontext;
#endif
return 0;
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 57de8b75162..bae2e6ee210 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -42,9 +42,6 @@ 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);
-extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
-
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/
@@ -78,6 +75,42 @@ struct rt_sigframe32 {
};
/*
+ * 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)
@@ -85,9 +118,13 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc)
int err;
while (1) {
lock_fpu_owner();
- own_fpu_inatomic(1);
- err = save_fp_context32(sc); /* this might fail */
- unlock_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 */
@@ -105,9 +142,13 @@ static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
int err, tmp __maybe_unused;
while (1) {
lock_fpu_owner();
- own_fpu_inatomic(0);
- err = restore_fp_context32(sc); /* this might fail */
- unlock_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 */
@@ -314,7 +355,7 @@ SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *,
return ret;
}
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
{
int err;
@@ -564,8 +605,8 @@ static int signal32_init(void)
save_fp_context32 = _save_fp_context32;
restore_fp_context32 = _restore_fp_context32;
} else {
- save_fp_context32 = fpu_emulator_save_context32;
- restore_fp_context32 = fpu_emulator_restore_context32;
+ save_fp_context32 = copy_fp_to_sigcontext32;
+ restore_fp_context32 = copy_fp_from_sigcontext32;
}
return 0;
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 126da74d4c5..df9e2bd9b2c 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -49,8 +49,10 @@ cpumask_t bmips_booted_mask;
unsigned long bmips_smp_boot_sp;
unsigned long bmips_smp_boot_gp;
-static void bmips_send_ipi_single(int cpu, unsigned int action);
-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
+static void bmips43xx_send_ipi_single(int cpu, unsigned int action);
+static void bmips5000_send_ipi_single(int cpu, unsigned int action);
+static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id);
+static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id);
/* SW interrupts 0,1 are used for interprocessor signaling */
#define IPI0_IRQ (MIPS_CPU_IRQ_BASE + 0)
@@ -64,49 +66,58 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
static void __init bmips_smp_setup(void)
{
int i, cpu = 1, boot_cpu = 0;
-
-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
int cpu_hw_intr;
- /* arbitration priority */
- clear_c0_brcm_cmt_ctrl(0x30);
-
- /* NBK and weak order flags */
- set_c0_brcm_config_0(0x30000);
-
- /* Find out if we are running on TP0 or TP1 */
- boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
-
- /*
- * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
- * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
- * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
- */
- if (boot_cpu == 0)
- cpu_hw_intr = 0x02;
- else
- cpu_hw_intr = 0x1d;
-
- change_c0_brcm_cmt_intr(0xf8018000, (cpu_hw_intr << 27) | (0x03 << 15));
-
- /* single core, 2 threads (2 pipelines) */
- max_cpus = 2;
-#elif defined(CONFIG_CPU_BMIPS5000)
- /* enable raceless SW interrupts */
- set_c0_brcm_config(0x03 << 22);
-
- /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
- change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
-
- /* N cores, 2 threads per core */
- max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
+ switch (current_cpu_type()) {
+ case CPU_BMIPS4350:
+ case CPU_BMIPS4380:
+ /* arbitration priority */
+ clear_c0_brcm_cmt_ctrl(0x30);
+
+ /* NBK and weak order flags */
+ set_c0_brcm_config_0(0x30000);
+
+ /* Find out if we are running on TP0 or TP1 */
+ boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
+
+ /*
+ * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other
+ * thread
+ * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
+ * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
+ */
+ if (boot_cpu == 0)
+ cpu_hw_intr = 0x02;
+ else
+ cpu_hw_intr = 0x1d;
+
+ change_c0_brcm_cmt_intr(0xf8018000,
+ (cpu_hw_intr << 27) | (0x03 << 15));
+
+ /* single core, 2 threads (2 pipelines) */
+ max_cpus = 2;
+
+ break;
+ case CPU_BMIPS5000:
+ /* enable raceless SW interrupts */
+ set_c0_brcm_config(0x03 << 22);
+
+ /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
+ change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
+
+ /* N cores, 2 threads per core */
+ max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
+
+ /* clear any pending SW interrupts */
+ for (i = 0; i < max_cpus; i++) {
+ write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
+ write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
+ }
- /* clear any pending SW interrupts */
- for (i = 0; i < max_cpus; i++) {
- write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
- write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
+ break;
+ default:
+ max_cpus = 1;
}
-#endif
if (!bmips_smp_enabled)
max_cpus = 1;
@@ -134,12 +145,26 @@ static void __init bmips_smp_setup(void)
*/
static void bmips_prepare_cpus(unsigned int max_cpus)
{
+ irqreturn_t (*bmips_ipi_interrupt)(int irq, void *dev_id);
+
+ switch (current_cpu_type()) {
+ case CPU_BMIPS4350:
+ case CPU_BMIPS4380:
+ bmips_ipi_interrupt = bmips43xx_ipi_interrupt;
+ break;
+ case CPU_BMIPS5000:
+ bmips_ipi_interrupt = bmips5000_ipi_interrupt;
+ break;
+ default:
+ return;
+ }
+
if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
"smp_ipi0", NULL))
- panic("Can't request IPI0 interrupt\n");
+ panic("Can't request IPI0 interrupt");
if (request_irq(IPI1_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
"smp_ipi1", NULL))
- panic("Can't request IPI1 interrupt\n");
+ panic("Can't request IPI1 interrupt");
}
/*
@@ -168,26 +193,39 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
pr_info("SMP: Booting CPU%d...\n", cpu);
- if (cpumask_test_cpu(cpu, &bmips_booted_mask))
- bmips_send_ipi_single(cpu, 0);
+ if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
+ switch (current_cpu_type()) {
+ case CPU_BMIPS4350:
+ case CPU_BMIPS4380:
+ bmips43xx_send_ipi_single(cpu, 0);
+ break;
+ case CPU_BMIPS5000:
+ bmips5000_send_ipi_single(cpu, 0);
+ break;
+ }
+ }
else {
-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
- /* Reset slave TP1 if booting from TP0 */
- if (cpu_logical_map(cpu) == 1)
- set_c0_brcm_cmt_ctrl(0x01);
-#elif defined(CONFIG_CPU_BMIPS5000)
- if (cpu & 0x01)
- write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
- else {
- /*
- * core N thread 0 was already booted; just
- * pulse the NMI line
- */
- bmips_write_zscm_reg(0x210, 0xc0000000);
- udelay(10);
- bmips_write_zscm_reg(0x210, 0x00);
+ switch (current_cpu_type()) {
+ case CPU_BMIPS4350:
+ case CPU_BMIPS4380:
+ /* Reset slave TP1 if booting from TP0 */
+ if (cpu_logical_map(cpu) == 1)
+ set_c0_brcm_cmt_ctrl(0x01);
+ break;
+ case CPU_BMIPS5000:
+ if (cpu & 0x01)
+ write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
+ else {
+ /*
+ * core N thread 0 was already booted; just
+ * pulse the NMI line
+ */
+ bmips_write_zscm_reg(0x210, 0xc0000000);
+ udelay(10);
+ bmips_write_zscm_reg(0x210, 0x00);
+ }
+ break;
}
-#endif
cpumask_set_cpu(cpu, &bmips_booted_mask);
}
}
@@ -199,26 +237,32 @@ static void bmips_init_secondary(void)
{
/* move NMI vector to kseg0, in case XKS01 is enabled */
-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
- void __iomem *cbr = BMIPS_GET_CBR();
+ void __iomem *cbr;
unsigned long old_vec;
unsigned long relo_vector;
int boot_cpu;
- boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
- relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
- BMIPS_RELO_VECTOR_CONTROL_1;
+ switch (current_cpu_type()) {
+ case CPU_BMIPS4350:
+ case CPU_BMIPS4380:
+ cbr = BMIPS_GET_CBR();
- old_vec = __raw_readl(cbr + relo_vector);
- __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
+ boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
+ relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
+ BMIPS_RELO_VECTOR_CONTROL_1;
- clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
-#elif defined(CONFIG_CPU_BMIPS5000)
- write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
- (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
+ old_vec = __raw_readl(cbr + relo_vector);
+ __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
- write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
-#endif
+ clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
+ break;
+ case CPU_BMIPS5000:
+ write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
+ (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
+
+ write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
+ break;
+ }
}
/*
@@ -237,15 +281,6 @@ static void bmips_smp_finish(void)
}
/*
- * Runs on CPU0 after all CPUs have been booted
- */
-static void bmips_cpus_done(void)
-{
-}
-
-#if defined(CONFIG_CPU_BMIPS5000)
-
-/*
* BMIPS5000 raceless IPIs
*
* Each CPU has two inbound SW IRQs which are independent of all other CPUs.
@@ -253,12 +288,12 @@ static void bmips_cpus_done(void)
* IPI1 is used for SMP_CALL_FUNCTION
*/
-static void bmips_send_ipi_single(int cpu, unsigned int action)
+static void bmips5000_send_ipi_single(int cpu, unsigned int action)
{
write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION));
}
-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
+static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
{
int action = irq - IPI0_IRQ;
@@ -272,7 +307,14 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-#else
+static void bmips5000_send_ipi_mask(const struct cpumask *mask,
+ unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu(i, mask)
+ bmips5000_send_ipi_single(i, action);
+}
/*
* BMIPS43xx racey IPIs
@@ -287,7 +329,7 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
static DEFINE_SPINLOCK(ipi_lock);
static DEFINE_PER_CPU(int, ipi_action_mask);
-static void bmips_send_ipi_single(int cpu, unsigned int action)
+static void bmips43xx_send_ipi_single(int cpu, unsigned int action)
{
unsigned long flags;
@@ -298,7 +340,7 @@ static void bmips_send_ipi_single(int cpu, unsigned int action)
spin_unlock_irqrestore(&ipi_lock, flags);
}
-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
+static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
{
unsigned long flags;
int action, cpu = irq - IPI0_IRQ;
@@ -317,15 +359,13 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-#endif /* BMIPS type */
-
-static void bmips_send_ipi_mask(const struct cpumask *mask,
+static void bmips43xx_send_ipi_mask(const struct cpumask *mask,
unsigned int action)
{
unsigned int i;
for_each_cpu(i, mask)
- bmips_send_ipi_single(i, action);
+ bmips43xx_send_ipi_single(i, action);
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -381,15 +421,28 @@ void __ref play_dead(void)
#endif /* CONFIG_HOTPLUG_CPU */
-struct plat_smp_ops bmips_smp_ops = {
+struct plat_smp_ops bmips43xx_smp_ops = {
+ .smp_setup = bmips_smp_setup,
+ .prepare_cpus = bmips_prepare_cpus,
+ .boot_secondary = bmips_boot_secondary,
+ .smp_finish = bmips_smp_finish,
+ .init_secondary = bmips_init_secondary,
+ .send_ipi_single = bmips43xx_send_ipi_single,
+ .send_ipi_mask = bmips43xx_send_ipi_mask,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = bmips_cpu_disable,
+ .cpu_die = bmips_cpu_die,
+#endif
+};
+
+struct plat_smp_ops bmips5000_smp_ops = {
.smp_setup = bmips_smp_setup,
.prepare_cpus = bmips_prepare_cpus,
.boot_secondary = bmips_boot_secondary,
.smp_finish = bmips_smp_finish,
.init_secondary = bmips_init_secondary,
- .cpus_done = bmips_cpus_done,
- .send_ipi_single = bmips_send_ipi_single,
- .send_ipi_mask = bmips_send_ipi_mask,
+ .send_ipi_single = bmips5000_send_ipi_single,
+ .send_ipi_mask = bmips5000_send_ipi_mask,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_disable = bmips_cpu_disable,
.cpu_die = bmips_cpu_die,
@@ -427,43 +480,47 @@ void bmips_ebase_setup(void)
BUG_ON(ebase != CKSEG0);
-#if defined(CONFIG_CPU_BMIPS4350)
- /*
- * BMIPS4350 cannot relocate the normal vectors, but it
- * can relocate the BEV=1 vectors. So CPU1 starts up at
- * the relocated BEV=1, IV=0 general exception vector @
- * 0xa000_0380.
- *
- * set_uncached_handler() is used here because:
- * - CPU1 will run this from uncached space
- * - None of the cacheflush functions are set up yet
- */
- set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
- &bmips_smp_int_vec, 0x80);
- __sync();
- return;
-#elif defined(CONFIG_CPU_BMIPS4380)
- /*
- * 0x8000_0000: reset/NMI (initially in kseg1)
- * 0x8000_0400: normal vectors
- */
- new_ebase = 0x80000400;
- cbr = BMIPS_GET_CBR();
- __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
- __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
-#elif defined(CONFIG_CPU_BMIPS5000)
- /*
- * 0x8000_0000: reset/NMI (initially in kseg1)
- * 0x8000_1000: normal vectors
- */
- new_ebase = 0x80001000;
- write_c0_brcm_bootvec(0xa0088008);
- write_c0_ebase(new_ebase);
- if (max_cpus > 2)
- bmips_write_zscm_reg(0xa0, 0xa008a008);
-#else
- return;
-#endif
+ switch (current_cpu_type()) {
+ case CPU_BMIPS4350:
+ /*
+ * BMIPS4350 cannot relocate the normal vectors, but it
+ * can relocate the BEV=1 vectors. So CPU1 starts up at
+ * the relocated BEV=1, IV=0 general exception vector @
+ * 0xa000_0380.
+ *
+ * set_uncached_handler() is used here because:
+ * - CPU1 will run this from uncached space
+ * - None of the cacheflush functions are set up yet
+ */
+ set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
+ &bmips_smp_int_vec, 0x80);
+ __sync();
+ return;
+ case CPU_BMIPS4380:
+ /*
+ * 0x8000_0000: reset/NMI (initially in kseg1)
+ * 0x8000_0400: normal vectors
+ */
+ new_ebase = 0x80000400;
+ cbr = BMIPS_GET_CBR();
+ __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
+ __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
+ break;
+ case CPU_BMIPS5000:
+ /*
+ * 0x8000_0000: reset/NMI (initially in kseg1)
+ * 0x8000_1000: normal vectors
+ */
+ new_ebase = 0x80001000;
+ write_c0_brcm_bootvec(0xa0088008);
+ write_c0_ebase(new_ebase);
+ if (max_cpus > 2)
+ bmips_write_zscm_reg(0xa0, 0xa008a008);
+ break;
+ default:
+ return;
+ }
+
board_nmi_handler_setup = &bmips_nmi_handler_setup;
ebase = new_ebase;
}
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index 5969f1e9b62..fc8a5155342 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -39,57 +39,9 @@
#include <asm/amon.h>
#include <asm/gic.h>
-static void ipi_call_function(unsigned int cpu)
-{
- pr_debug("CPU%d: %s cpu %d status %08x\n",
- smp_processor_id(), __func__, cpu, read_c0_status());
-
- gic_send_ipi(plat_ipi_call_int_xlate(cpu));
-}
-
-
-static void ipi_resched(unsigned int cpu)
-{
- pr_debug("CPU%d: %s cpu %d status %08x\n",
- smp_processor_id(), __func__, cpu, read_c0_status());
-
- gic_send_ipi(plat_ipi_resched_int_xlate(cpu));
-}
-
-/*
- * FIXME: This isn't restricted to CMP
- * The SMVP kernel could use GIC interrupts if available
- */
-void cmp_send_ipi_single(int cpu, unsigned int action)
-{
- unsigned long flags;
-
- local_irq_save(flags);
-
- switch (action) {
- case SMP_CALL_FUNCTION:
- ipi_call_function(cpu);
- break;
-
- case SMP_RESCHEDULE_YOURSELF:
- ipi_resched(cpu);
- break;
- }
-
- local_irq_restore(flags);
-}
-
-static void cmp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
-{
- unsigned int i;
-
- for_each_cpu(i, mask)
- cmp_send_ipi_single(i, action);
-}
-
static void cmp_init_secondary(void)
{
- struct cpuinfo_mips *c = &current_cpu_data;
+ struct cpuinfo_mips *c __maybe_unused = &current_cpu_data;
/* Assume GIC is present */
change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 |
@@ -97,15 +49,11 @@ static void cmp_init_secondary(void)
/* Enable per-cpu interrupts: platform specific */
- c->core = (read_c0_ebase() >> 1) & 0x1ff;
-#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
+#ifdef CONFIG_MIPS_MT_SMP
if (cpu_has_mipsmt)
c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) &
TCBIND_CURVPE;
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
- c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
-#endif
}
static void cmp_smp_finish(void)
@@ -124,11 +72,6 @@ static void cmp_smp_finish(void)
local_irq_enable();
}
-static void cmp_cpus_done(void)
-{
- pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
-}
-
/*
* Setup the PC, SP, and GP of a secondary processor and start it running
* smp_bootstrap is the place to resume from
@@ -184,10 +127,6 @@ void __init cmp_smp_setup(void)
unsigned int mvpconf0 = read_c0_mvpconf0();
nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
-#elif defined(CONFIG_MIPS_MT_SMTC)
- unsigned int mvpconf0 = read_c0_mvpconf0();
-
- nvpe = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
#endif
smp_num_siblings = nvpe;
}
@@ -199,19 +138,21 @@ void __init cmp_prepare_cpus(unsigned int max_cpus)
pr_debug("SMPCMP: CPU%d: %s max_cpus=%d\n",
smp_processor_id(), __func__, max_cpus);
+#ifdef CONFIG_MIPS_MT
/*
* FIXME: some of these options are per-system, some per-core and
* some per-cpu
*/
mips_mt_set_cpuoptions();
+#endif
+
}
struct plat_smp_ops cmp_smp_ops = {
- .send_ipi_single = cmp_send_ipi_single,
- .send_ipi_mask = cmp_send_ipi_mask,
+ .send_ipi_single = gic_send_ipi_single,
+ .send_ipi_mask = gic_send_ipi_mask,
.init_secondary = cmp_init_secondary,
.smp_finish = cmp_smp_finish,
- .cpus_done = cmp_cpus_done,
.boot_secondary = cmp_boot_secondary,
.smp_setup = cmp_smp_setup,
.prepare_cpus = cmp_prepare_cpus,
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
new file mode 100644
index 00000000000..949f2c6827a
--- /dev/null
+++ b/arch/mips/kernel/smp-cps.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2013 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/io.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cacheflush.h>
+#include <asm/gic.h>
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
+#include <asm/mips_mt.h>
+#include <asm/mipsregs.h>
+#include <asm/pm-cps.h>
+#include <asm/smp-cps.h>
+#include <asm/time.h>
+#include <asm/uasm.h>
+
+static DECLARE_BITMAP(core_power, NR_CPUS);
+
+struct core_boot_config *mips_cps_core_bootcfg;
+
+static unsigned core_vpe_count(unsigned core)
+{
+ unsigned cfg;
+
+ if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
+ return 1;
+
+ write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+ cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK;
+ return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
+}
+
+static void __init cps_smp_setup(void)
+{
+ unsigned int ncores, nvpes, core_vpes;
+ int c, v;
+
+ /* Detect & record VPE topology */
+ ncores = mips_cm_numcores();
+ pr_info("VPE topology ");
+ for (c = nvpes = 0; c < ncores; c++) {
+ core_vpes = core_vpe_count(c);
+ pr_cont("%c%u", c ? ',' : '{', core_vpes);
+
+ /* Use the number of VPEs in core 0 for smp_num_siblings */
+ if (!c)
+ smp_num_siblings = core_vpes;
+
+ for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
+ cpu_data[nvpes + v].core = c;
+#ifdef CONFIG_MIPS_MT_SMP
+ cpu_data[nvpes + v].vpe_id = v;
+#endif
+ }
+
+ nvpes += core_vpes;
+ }
+ pr_cont("} total %u\n", nvpes);
+
+ /* Indicate present CPUs (CPU being synonymous with VPE) */
+ for (v = 0; v < min_t(unsigned, nvpes, NR_CPUS); v++) {
+ set_cpu_possible(v, true);
+ set_cpu_present(v, true);
+ __cpu_number_map[v] = v;
+ __cpu_logical_map[v] = v;
+ }
+
+ /* Set a coherent default CCA (CWB) */
+ change_c0_config(CONF_CM_CMASK, 0x5);
+
+ /* Core 0 is powered up (we're running on it) */
+ bitmap_set(core_power, 0, 1);
+
+ /* Initialise core 0 */
+ mips_cps_core_init();
+
+ /* Make core 0 coherent with everything */
+ write_gcr_cl_coherence(0xff);
+}
+
+static void __init cps_prepare_cpus(unsigned int max_cpus)
+{
+ unsigned ncores, core_vpes, c, cca;
+ bool cca_unsuitable;
+ u32 *entry_code;
+
+ mips_mt_set_cpuoptions();
+
+ /* Detect whether the CCA is unsuited to multi-core SMP */
+ cca = read_c0_config() & CONF_CM_CMASK;
+ switch (cca) {
+ case 0x4: /* CWBE */
+ case 0x5: /* CWB */
+ /* The CCA is coherent, multi-core is fine */
+ cca_unsuitable = false;
+ break;
+
+ default:
+ /* CCA is not coherent, multi-core is not usable */
+ cca_unsuitable = true;
+ }
+
+ /* Warn the user if the CCA prevents multi-core */
+ ncores = mips_cm_numcores();
+ if (cca_unsuitable && ncores > 1) {
+ pr_warn("Using only one core due to unsuitable CCA 0x%x\n",
+ cca);
+
+ for_each_present_cpu(c) {
+ if (cpu_data[c].core)
+ set_cpu_present(c, false);
+ }
+ }
+
+ /*
+ * 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);
+ dma_cache_wback_inv((unsigned long)&mips_cps_core_entry,
+ (void *)entry_code - (void *)&mips_cps_core_entry);
+
+ /* Allocate core boot configuration structs */
+ mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
+ GFP_KERNEL);
+ if (!mips_cps_core_bootcfg) {
+ pr_err("Failed to allocate boot config for %u cores\n", ncores);
+ goto err_out;
+ }
+
+ /* Allocate VPE boot configuration structs */
+ for (c = 0; c < ncores; c++) {
+ core_vpes = core_vpe_count(c);
+ mips_cps_core_bootcfg[c].vpe_config = kcalloc(core_vpes,
+ sizeof(*mips_cps_core_bootcfg[c].vpe_config),
+ GFP_KERNEL);
+ if (!mips_cps_core_bootcfg[c].vpe_config) {
+ pr_err("Failed to allocate %u VPE boot configs\n",
+ core_vpes);
+ goto err_out;
+ }
+ }
+
+ /* Mark this CPU as booted */
+ atomic_set(&mips_cps_core_bootcfg[current_cpu_data.core].vpe_mask,
+ 1 << cpu_vpe_id(&current_cpu_data));
+
+ return;
+err_out:
+ /* Clean up allocations */
+ if (mips_cps_core_bootcfg) {
+ for (c = 0; c < ncores; c++)
+ kfree(mips_cps_core_bootcfg[c].vpe_config);
+ kfree(mips_cps_core_bootcfg);
+ mips_cps_core_bootcfg = NULL;
+ }
+
+ /* Effectively disable SMP by declaring CPUs not present */
+ for_each_possible_cpu(c) {
+ if (c == 0)
+ continue;
+ set_cpu_present(c, false);
+ }
+}
+
+static void boot_core(unsigned core)
+{
+ u32 access;
+
+ /* Select the appropriate core */
+ write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+
+ /* Set its reset vector */
+ write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
+
+ /* Ensure its coherency is disabled */
+ write_gcr_co_coherence(0);
+
+ /* Ensure the core can access the GCRs */
+ access = read_gcr_access();
+ access |= 1 << (CM_GCR_ACCESS_ACCESSEN_SHF + core);
+ write_gcr_access(access);
+
+ if (mips_cpc_present()) {
+ /* Reset the core */
+ mips_cpc_lock_other(core);
+ write_cpc_co_cmd(CPC_Cx_CMD_RESET);
+ mips_cpc_unlock_other();
+ } else {
+ /* Take the core out of reset */
+ write_gcr_co_reset_release(0);
+ }
+
+ /* The core is now powered up */
+ bitmap_set(core_power, core, 1);
+}
+
+static void remote_vpe_boot(void *dummy)
+{
+ mips_cps_boot_vpes();
+}
+
+static void cps_boot_secondary(int cpu, struct task_struct *idle)
+{
+ unsigned core = cpu_data[cpu].core;
+ unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
+ struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
+ struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id];
+ unsigned int remote;
+ int err;
+
+ vpe_cfg->pc = (unsigned long)&smp_bootstrap;
+ vpe_cfg->sp = __KSTK_TOS(idle);
+ vpe_cfg->gp = (unsigned long)task_thread_info(idle);
+
+ atomic_or(1 << cpu_vpe_id(&cpu_data[cpu]), &core_cfg->vpe_mask);
+
+ preempt_disable();
+
+ if (!test_bit(core, core_power)) {
+ /* Boot a VPE on a powered down core */
+ boot_core(core);
+ goto out;
+ }
+
+ if (core != current_cpu_data.core) {
+ /* Boot a VPE on another powered up core */
+ for (remote = 0; remote < NR_CPUS; remote++) {
+ if (cpu_data[remote].core != core)
+ continue;
+ if (cpu_online(remote))
+ break;
+ }
+ BUG_ON(remote >= NR_CPUS);
+
+ err = smp_call_function_single(remote, remote_vpe_boot,
+ NULL, 1);
+ if (err)
+ panic("Failed to call remote CPU\n");
+ goto out;
+ }
+
+ BUG_ON(!cpu_has_mipsmt);
+
+ /* Boot a VPE on this core */
+ mips_cps_boot_vpes();
+out:
+ preempt_enable();
+}
+
+static void cps_init_secondary(void)
+{
+ /* Disable MT - we only want to run 1 TC per VPE */
+ if (cpu_has_mipsmt)
+ dmt();
+
+ change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
+ STATUSF_IP6 | STATUSF_IP7);
+}
+
+static void cps_smp_finish(void)
+{
+ write_c0_compare(read_c0_count() + (8 * mips_hpt_frequency / HZ));
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+ /* If we have an FPU, enroll ourselves in the FPU-full mask */
+ if (cpu_has_fpu)
+ cpu_set(smp_processor_id(), mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+ local_irq_enable();
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int cps_cpu_disable(void)
+{
+ unsigned cpu = smp_processor_id();
+ struct core_boot_config *core_cfg;
+
+ if (!cpu)
+ return -EBUSY;
+
+ if (!cps_pm_support_state(CPS_PM_POWER_GATED))
+ return -EINVAL;
+
+ core_cfg = &mips_cps_core_bootcfg[current_cpu_data.core];
+ atomic_sub(1 << cpu_vpe_id(&current_cpu_data), &core_cfg->vpe_mask);
+ smp_mb__after_atomic();
+ set_cpu_online(cpu, false);
+ cpu_clear(cpu, cpu_callin_map);
+
+ return 0;
+}
+
+static DECLARE_COMPLETION(cpu_death_chosen);
+static unsigned cpu_death_sibling;
+static enum {
+ CPU_DEATH_HALT,
+ CPU_DEATH_POWER,
+} cpu_death;
+
+void play_dead(void)
+{
+ unsigned cpu, core;
+
+ local_irq_disable();
+ idle_task_exit();
+ cpu = smp_processor_id();
+ cpu_death = CPU_DEATH_POWER;
+
+ if (cpu_has_mipsmt) {
+ core = cpu_data[cpu].core;
+
+ /* Look for another online VPE within the core */
+ for_each_online_cpu(cpu_death_sibling) {
+ if (cpu_data[cpu_death_sibling].core != core)
+ continue;
+
+ /*
+ * There is an online VPE within the core. Just halt
+ * this TC and leave the core alone.
+ */
+ cpu_death = CPU_DEATH_HALT;
+ break;
+ }
+ }
+
+ /* This CPU has chosen its way out */
+ complete(&cpu_death_chosen);
+
+ if (cpu_death == CPU_DEATH_HALT) {
+ /* Halt this TC */
+ write_c0_tchalt(TCHALT_H);
+ instruction_hazard();
+ } else {
+ /* Power down the core */
+ cps_pm_enter_state(CPS_PM_POWER_GATED);
+ }
+
+ /* This should never be reached */
+ panic("Failed to offline CPU %u", cpu);
+}
+
+static void wait_for_sibling_halt(void *ptr_cpu)
+{
+ unsigned cpu = (unsigned)ptr_cpu;
+ unsigned vpe_id = cpu_data[cpu].vpe_id;
+ unsigned halted;
+ unsigned long flags;
+
+ do {
+ local_irq_save(flags);
+ settc(vpe_id);
+ halted = read_tc_c0_tchalt();
+ local_irq_restore(flags);
+ } while (!(halted & TCHALT_H));
+}
+
+static void cps_cpu_die(unsigned int cpu)
+{
+ unsigned core = cpu_data[cpu].core;
+ unsigned stat;
+ int err;
+
+ /* Wait for the cpu to choose its way out */
+ if (!wait_for_completion_timeout(&cpu_death_chosen,
+ msecs_to_jiffies(5000))) {
+ pr_err("CPU%u: didn't offline\n", cpu);
+ return;
+ }
+
+ /*
+ * Now wait for the CPU to actually offline. Without doing this that
+ * offlining may race with one or more of:
+ *
+ * - Onlining the CPU again.
+ * - Powering down the core if another VPE within it is offlined.
+ * - A sibling VPE entering a non-coherent state.
+ *
+ * In the non-MT halt case (ie. infinite loop) the CPU is doing nothing
+ * with which we could race, so do nothing.
+ */
+ if (cpu_death == CPU_DEATH_POWER) {
+ /*
+ * Wait for the core to enter a powered down or clock gated
+ * state, the latter happening when a JTAG probe is connected
+ * in which case the CPC will refuse to power down the core.
+ */
+ do {
+ mips_cpc_lock_other(core);
+ stat = read_cpc_co_stat_conf();
+ stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK;
+ mips_cpc_unlock_other();
+ } while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 &&
+ stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 &&
+ stat != CPC_Cx_STAT_CONF_SEQSTATE_U2);
+
+ /* Indicate the core is powered off */
+ bitmap_clear(core_power, core, 1);
+ } else if (cpu_has_mipsmt) {
+ /*
+ * Have a CPU with access to the offlined CPUs registers wait
+ * for its TC to halt.
+ */
+ err = smp_call_function_single(cpu_death_sibling,
+ wait_for_sibling_halt,
+ (void *)cpu, 1);
+ if (err)
+ panic("Failed to call remote sibling CPU\n");
+ }
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static struct plat_smp_ops cps_smp_ops = {
+ .smp_setup = cps_smp_setup,
+ .prepare_cpus = cps_prepare_cpus,
+ .boot_secondary = cps_boot_secondary,
+ .init_secondary = cps_init_secondary,
+ .smp_finish = cps_smp_finish,
+ .send_ipi_single = gic_send_ipi_single,
+ .send_ipi_mask = gic_send_ipi_mask,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = cps_cpu_disable,
+ .cpu_die = cps_cpu_die,
+#endif
+};
+
+bool mips_cps_smp_in_use(void)
+{
+ extern struct plat_smp_ops *mp_ops;
+ return mp_ops == &cps_smp_ops;
+}
+
+int register_cps_smp_ops(void)
+{
+ if (!mips_cm_present()) {
+ pr_warn("MIPS CPS SMP unable to proceed without a CM\n");
+ return -ENODEV;
+ }
+
+ /* check we have a GIC - we need one for IPIs */
+ if (!(read_gcr_gic_status() & CM_GCR_GIC_STATUS_EX_MSK)) {
+ pr_warn("MIPS CPS SMP unable to proceed without a GIC\n");
+ return -ENODEV;
+ }
+
+ register_smp_ops(&cps_smp_ops);
+ return 0;
+}
diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c
new file mode 100644
index 00000000000..3b21a96d1cc
--- /dev/null
+++ b/arch/mips/kernel/smp-gic.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * Based on smp-cmp.c:
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ * Author: Chris Dearman (chris@mips.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/printk.h>
+
+#include <asm/gic.h>
+#include <asm/mips-cpc.h>
+#include <asm/smp-ops.h>
+
+void gic_send_ipi_single(int cpu, unsigned int action)
+{
+ unsigned long flags;
+ unsigned int intr;
+ unsigned int core = cpu_data[cpu].core;
+
+ pr_debug("CPU%d: %s cpu %d action %u status %08x\n",
+ smp_processor_id(), __func__, cpu, action, read_c0_status());
+
+ local_irq_save(flags);
+
+ switch (action) {
+ case SMP_CALL_FUNCTION:
+ intr = plat_ipi_call_int_xlate(cpu);
+ break;
+
+ case SMP_RESCHEDULE_YOURSELF:
+ intr = plat_ipi_resched_int_xlate(cpu);
+ break;
+
+ default:
+ BUG();
+ }
+
+ gic_send_ipi(intr);
+
+ if (mips_cpc_present() && (core != current_cpu_data.core)) {
+ while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+ mips_cpc_lock_other(core);
+ write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
+ mips_cpc_unlock_other();
+ }
+ }
+
+ local_irq_restore(flags);
+}
+
+void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu(i, mask)
+ gic_send_ipi_single(i, action);
+}
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 57a3f7a2b37..3babf6e4f89 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -71,6 +71,7 @@ static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0,
/* Record this as available CPU */
set_cpu_possible(tc, true);
+ set_cpu_present(tc, true);
__cpu_number_map[tc] = ++ncpu;
__cpu_logical_map[ncpu] = tc;
}
@@ -118,6 +119,12 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action)
unsigned long flags;
int vpflags;
+#ifdef CONFIG_IRQ_GIC
+ if (gic_present) {
+ gic_send_ipi_single(cpu, action);
+ return;
+ }
+#endif
local_irq_save(flags);
vpflags = dvpe(); /* can't access the other CPU's registers whilst MVPE enabled */
@@ -176,10 +183,6 @@ static void vsmp_smp_finish(void)
local_irq_enable();
}
-static void vsmp_cpus_done(void)
-{
-}
-
/*
* Setup the PC, SP, and GP of a secondary processor and start it
* running!
@@ -280,8 +283,29 @@ struct plat_smp_ops vsmp_smp_ops = {
.send_ipi_mask = vsmp_send_ipi_mask,
.init_secondary = vsmp_init_secondary,
.smp_finish = vsmp_smp_finish,
- .cpus_done = vsmp_cpus_done,
.boot_secondary = vsmp_boot_secondary,
.smp_setup = vsmp_smp_setup,
.prepare_cpus = vsmp_prepare_cpus,
};
+
+static int proc_cpuinfo_chain_call(struct notifier_block *nfb,
+ unsigned long action_unused, void *data)
+{
+ struct proc_cpuinfo_notifier_args *pcn = data;
+ struct seq_file *m = pcn->m;
+ unsigned long n = pcn->n;
+
+ if (!cpu_has_mipsmt)
+ return NOTIFY_OK;
+
+ seq_printf(m, "VPE\t\t\t: %d\n", cpu_data[n].vpe_id);
+
+ return NOTIFY_OK;
+}
+
+static int __init proc_cpuinfo_notifier_init(void)
+{
+ return proc_cpuinfo_notifier(proc_cpuinfo_chain_call, 0);
+}
+
+subsys_initcall(proc_cpuinfo_notifier_init);
diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c
index 7fde3e4d978..17878d71ef2 100644
--- a/arch/mips/kernel/smp-up.c
+++ b/arch/mips/kernel/smp-up.c
@@ -36,11 +36,6 @@ static void up_smp_finish(void)
{
}
-/* Hook for after all CPUs are online */
-static void up_cpus_done(void)
-{
-}
-
/*
* Firmware CPU startup hook
*/
@@ -73,7 +68,6 @@ struct plat_smp_ops up_smp_ops = {
.send_ipi_mask = up_send_ipi_mask,
.init_secondary = up_init_secondary,
.smp_finish = up_smp_finish,
- .cpus_done = up_cpus_done,
.boot_secondary = up_boot_secondary,
.smp_setup = up_smp_setup,
.prepare_cpus = up_prepare_cpus,
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 5c208ed8f85..9bad52ede90 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -43,10 +43,6 @@
#include <asm/time.h>
#include <asm/setup.h>
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/mipsmtregs.h>
-#endif /* CONFIG_MIPS_MT_SMTC */
-
volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
@@ -66,6 +62,8 @@ EXPORT_SYMBOL(cpu_sibling_map);
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
+cpumask_t cpu_coherent_mask;
+
static inline void set_cpu_sibling_map(int cpu)
{
int i;
@@ -102,12 +100,6 @@ asmlinkage void start_secondary(void)
{
unsigned int cpu;
-#ifdef CONFIG_MIPS_MT_SMTC
- /* Only do cpu_probe for first TC of CPU */
- if ((read_c0_tcbind() & TCBIND_CURTC) != 0)
- __cpu_name[smp_processor_id()] = __cpu_name[0];
- else
-#endif /* CONFIG_MIPS_MT_SMTC */
cpu_probe();
cpu_report();
per_cpu_trap_init(false);
@@ -124,6 +116,7 @@ asmlinkage void start_secondary(void)
cpu = smp_processor_id();
cpu_data[cpu].udelay_val = loops_per_jiffy;
+ cpu_set(cpu, cpu_coherent_mask);
notify_cpu_starting(cpu);
set_cpu_online(cpu, true);
@@ -150,7 +143,6 @@ asmlinkage void start_secondary(void)
void __irq_entry smp_call_function_interrupt(void)
{
irq_enter();
- generic_smp_call_function_single_interrupt();
generic_smp_call_function_interrupt();
irq_exit();
}
@@ -174,7 +166,6 @@ void smp_send_stop(void)
void __init smp_cpus_done(unsigned int max_cpus)
{
- mp_ops->cpus_done();
}
/* called from main before smp_init() */
@@ -187,6 +178,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
#ifndef CONFIG_HOTPLUG_CPU
init_cpu_present(cpu_possible_mask);
#endif
+ cpumask_copy(&cpu_coherent_mask, cpu_possible_mask);
}
/* preload SMP state for boot cpu */
@@ -239,13 +231,10 @@ static void flush_tlb_mm_ipi(void *mm)
* o collapses to normal function call on UP kernels
* o collapses to normal function call on systems with a single shared
* primary cache.
- * o CONFIG_MIPS_MT_SMTC currently implies there is only one physical core.
*/
static inline void smp_on_other_tlbs(void (*func) (void *info), void *info)
{
-#ifndef CONFIG_MIPS_MT_SMTC
smp_call_function(func, info, 1);
-#endif
}
static inline void smp_on_each_tlb(void (*func) (void *info), void *info)
@@ -405,3 +394,46 @@ void dump_send_ipi(void (*dump_ipi_callback)(void *))
}
EXPORT_SYMBOL(dump_send_ipi);
#endif
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+
+static DEFINE_PER_CPU(atomic_t, tick_broadcast_count);
+static DEFINE_PER_CPU(struct call_single_data, tick_broadcast_csd);
+
+void tick_broadcast(const struct cpumask *mask)
+{
+ atomic_t *count;
+ struct call_single_data *csd;
+ int cpu;
+
+ for_each_cpu(cpu, mask) {
+ count = &per_cpu(tick_broadcast_count, cpu);
+ csd = &per_cpu(tick_broadcast_csd, cpu);
+
+ if (atomic_inc_return(count) == 1)
+ smp_call_function_single_async(cpu, csd);
+ }
+}
+
+static void tick_broadcast_callee(void *info)
+{
+ int cpu = smp_processor_id();
+ tick_receive_broadcast();
+ atomic_set(&per_cpu(tick_broadcast_count, cpu), 0);
+}
+
+static int __init tick_broadcast_init(void)
+{
+ struct call_single_data *csd;
+ int cpu;
+
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ csd = &per_cpu(tick_broadcast_csd, cpu);
+ csd->func = tick_broadcast_callee;
+ }
+
+ return 0;
+}
+early_initcall(tick_broadcast_init);
+
+#endif /* CONFIG_GENERIC_CLOCKEVENTS_BROADCAST */
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
deleted file mode 100644
index 2866863a39d..00000000000
--- a/arch/mips/kernel/smtc-asm.S
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Assembly Language Functions for MIPS MT SMTC support
- */
-
-/*
- * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */
-
-#include <asm/regdef.h>
-#include <asm/asmmacro.h>
-#include <asm/stackframe.h>
-#include <asm/irqflags.h>
-
-/*
- * "Software Interrupt" linkage.
- *
- * This is invoked when an "Interrupt" is sent from one TC to another,
- * where the TC to be interrupted is halted, has it's Restart address
- * and Status values saved by the "remote control" thread, then modified
- * to cause execution to begin here, in kenel mode. This code then
- * disguises the TC state as that of an exception and transfers
- * control to the general exception or vectored interrupt handler.
- */
- .set noreorder
-
-/*
-The __smtc_ipi_vector would use k0 and k1 as temporaries and
-1) Set EXL (this is per-VPE, so this can't be done by proxy!)
-2) Restore the K/CU and IXMT bits to the pre "exception" state
- (EXL means no interrupts and access to the kernel map).
-3) Set EPC to be the saved value of TCRestart.
-4) Jump to the exception handler entry point passed by the sender.
-
-CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED??
-*/
-
-/*
- * Reviled and slandered vision: Set EXL and restore K/CU/IXMT
- * state of pre-halt thread, then save everything and call
- * thought some function pointer to imaginary_exception, which
- * will parse a register value or memory message queue to
- * deliver things like interprocessor interrupts. On return
- * from that function, jump to the global ret_from_irq code
- * to invoke the scheduler and return as appropriate.
- */
-
-#define PT_PADSLOT4 (PT_R0-8)
-#define PT_PADSLOT5 (PT_R0-4)
-
- .text
- .align 5
-FEXPORT(__smtc_ipi_vector)
-#ifdef CONFIG_CPU_MICROMIPS
- nop
-#endif
- .set noat
- /* Disable thread scheduling to make Status update atomic */
- DMT 27 # dmt k1
- _ehb
- /* Set EXL */
- mfc0 k0,CP0_STATUS
- ori k0,k0,ST0_EXL
- mtc0 k0,CP0_STATUS
- _ehb
- /* Thread scheduling now inhibited by EXL. Restore TE state. */
- andi k1,k1,VPECONTROL_TE
- beqz k1,1f
- emt
-1:
- /*
- * The IPI sender has put some information on the anticipated
- * kernel stack frame. If we were in user mode, this will be
- * built above the saved kernel SP. If we were already in the
- * kernel, it will be built above the current CPU SP.
- *
- * Were we in kernel mode, as indicated by CU0?
- */
- sll k1,k0,3
- .set noreorder
- bltz k1,2f
- move k1,sp
- .set reorder
- /*
- * If previously in user mode, set CU0 and use kernel stack.
- */
- li k1,ST0_CU0
- or k1,k1,k0
- mtc0 k1,CP0_STATUS
- _ehb
- get_saved_sp
- /* Interrupting TC will have pre-set values in slots in the new frame */
-2: subu k1,k1,PT_SIZE
- /* Load TCStatus Value */
- lw k0,PT_TCSTATUS(k1)
- /* Write it to TCStatus to restore CU/KSU/IXMT state */
- mtc0 k0,$2,1
- _ehb
- lw k0,PT_EPC(k1)
- mtc0 k0,CP0_EPC
- /* Save all will redundantly recompute the SP, but use it for now */
- SAVE_ALL
- CLI
- TRACE_IRQS_OFF
- /* Function to be invoked passed stack pad slot 5 */
- lw t0,PT_PADSLOT5(sp)
- /* Argument from sender passed in stack pad slot 4 */
- lw a0,PT_PADSLOT4(sp)
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
- PTR_LA ra, ret_from_irq
- jr t0
-
-/*
- * Called from idle loop to provoke processing of queued IPIs
- * First IPI message in queue passed as argument.
- */
-
-LEAF(self_ipi)
- /* Before anything else, block interrupts */
- mfc0 t0,CP0_TCSTATUS
- ori t1,t0,TCSTATUS_IXMT
- mtc0 t1,CP0_TCSTATUS
- _ehb
- /* We know we're in kernel mode, so prepare stack frame */
- subu t1,sp,PT_SIZE
- sw ra,PT_EPC(t1)
- sw a0,PT_PADSLOT4(t1)
- la t2,ipi_decode
- sw t2,PT_PADSLOT5(t1)
- /* Save pre-disable value of TCStatus */
- sw t0,PT_TCSTATUS(t1)
- j __smtc_ipi_vector
- nop
-END(self_ipi)
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
deleted file mode 100644
index c10aa84c9fa..00000000000
--- a/arch/mips/kernel/smtc-proc.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * /proc hooks for SMTC kernel
- * Copyright (C) 2005 Mips Technologies, Inc
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-
-#include <asm/cpu.h>
-#include <asm/processor.h>
-#include <linux/atomic.h>
-#include <asm/hardirq.h>
-#include <asm/mmu_context.h>
-#include <asm/mipsregs.h>
-#include <asm/cacheflush.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#include <asm/smtc_proc.h>
-
-/*
- * /proc diagnostic and statistics hooks
- */
-
-/*
- * Statistics gathered
- */
-unsigned long selfipis[NR_CPUS];
-
-struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
-
-atomic_t smtc_fpu_recoveries;
-
-static int smtc_proc_show(struct seq_file *m, void *v)
-{
- int i;
- extern unsigned long ebase;
-
- seq_printf(m, "SMTC Status Word: 0x%08x\n", smtc_status);
- seq_printf(m, "Config7: 0x%08x\n", read_c0_config7());
- seq_printf(m, "EBASE: 0x%08lx\n", ebase);
- seq_printf(m, "Counter Interrupts taken per CPU (TC)\n");
- for (i=0; i < NR_CPUS; i++)
- seq_printf(m, "%d: %ld\n", i, smtc_cpu_stats[i].timerints);
- seq_printf(m, "Self-IPIs by CPU:\n");
- for(i = 0; i < NR_CPUS; i++)
- seq_printf(m, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
- seq_printf(m, "%d Recoveries of \"stolen\" FPU\n",
- atomic_read(&smtc_fpu_recoveries));
- return 0;
-}
-
-static int smtc_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, smtc_proc_show, NULL);
-}
-
-static const struct file_operations smtc_proc_fops = {
- .open = smtc_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-void init_smtc_stats(void)
-{
- int i;
-
- for (i=0; i<NR_CPUS; i++) {
- smtc_cpu_stats[i].timerints = 0;
- smtc_cpu_stats[i].selfipis = 0;
- }
-
- atomic_set(&smtc_fpu_recoveries, 0);
-
- proc_create("smtc", 0444, NULL, &smtc_proc_fops);
-}
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
deleted file mode 100644
index dfc1b911be0..00000000000
--- a/arch/mips/kernel/smtc.c
+++ /dev/null
@@ -1,1528 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) 2004 Mips Technologies, Inc
- * Copyright (C) 2008 Kevin D. Kissell
- */
-
-#include <linux/clockchips.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/ftrace.h>
-#include <linux/slab.h>
-
-#include <asm/cpu.h>
-#include <asm/processor.h>
-#include <linux/atomic.h>
-#include <asm/hardirq.h>
-#include <asm/hazards.h>
-#include <asm/irq.h>
-#include <asm/idle.h>
-#include <asm/mmu_context.h>
-#include <asm/mipsregs.h>
-#include <asm/cacheflush.h>
-#include <asm/time.h>
-#include <asm/addrspace.h>
-#include <asm/smtc.h>
-#include <asm/smtc_proc.h>
-#include <asm/setup.h>
-
-/*
- * SMTC Kernel needs to manipulate low-level CPU interrupt mask
- * in do_IRQ. These are passed in setup_irq_smtc() and stored
- * in this table.
- */
-unsigned long irq_hwmask[NR_IRQS];
-
-#define LOCK_MT_PRA() \
- local_irq_save(flags); \
- mtflags = dmt()
-
-#define UNLOCK_MT_PRA() \
- emt(mtflags); \
- local_irq_restore(flags)
-
-#define LOCK_CORE_PRA() \
- local_irq_save(flags); \
- mtflags = dvpe()
-
-#define UNLOCK_CORE_PRA() \
- evpe(mtflags); \
- local_irq_restore(flags)
-
-/*
- * Data structures purely associated with SMTC parallelism
- */
-
-
-/*
- * Table for tracking ASIDs whose lifetime is prolonged.
- */
-
-asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
-
-/*
- * Number of InterProcessor Interrupt (IPI) message buffers to allocate
- */
-
-#define IPIBUF_PER_CPU 4
-
-struct smtc_ipi_q IPIQ[NR_CPUS];
-static struct smtc_ipi_q freeIPIq;
-
-
-/*
- * Number of FPU contexts for each VPE
- */
-
-static int smtc_nconf1[MAX_SMTC_VPES];
-
-
-/* Forward declarations */
-
-void ipi_decode(struct smtc_ipi *);
-static void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
-static void setup_cross_vpe_interrupts(unsigned int nvpe);
-void init_smtc_stats(void);
-
-/* Global SMTC Status */
-
-unsigned int smtc_status;
-
-/* Boot command line configuration overrides */
-
-static int vpe0limit;
-static int ipibuffers;
-static int nostlb;
-static int asidmask;
-unsigned long smtc_asid_mask = 0xff;
-
-static int __init vpe0tcs(char *str)
-{
- get_option(&str, &vpe0limit);
-
- return 1;
-}
-
-static int __init ipibufs(char *str)
-{
- get_option(&str, &ipibuffers);
- return 1;
-}
-
-static int __init stlb_disable(char *s)
-{
- nostlb = 1;
- return 1;
-}
-
-static int __init asidmask_set(char *str)
-{
- get_option(&str, &asidmask);
- switch (asidmask) {
- case 0x1:
- case 0x3:
- case 0x7:
- case 0xf:
- case 0x1f:
- case 0x3f:
- case 0x7f:
- case 0xff:
- smtc_asid_mask = (unsigned long)asidmask;
- break;
- default:
- printk("ILLEGAL ASID mask 0x%x from command line\n", asidmask);
- }
- return 1;
-}
-
-__setup("vpe0tcs=", vpe0tcs);
-__setup("ipibufs=", ipibufs);
-__setup("nostlb", stlb_disable);
-__setup("asidmask=", asidmask_set);
-
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
-
-static int hang_trig;
-
-static int __init hangtrig_enable(char *s)
-{
- hang_trig = 1;
- return 1;
-}
-
-
-__setup("hangtrig", hangtrig_enable);
-
-#define DEFAULT_BLOCKED_IPI_LIMIT 32
-
-static int timerq_limit = DEFAULT_BLOCKED_IPI_LIMIT;
-
-static int __init tintq(char *str)
-{
- get_option(&str, &timerq_limit);
- return 1;
-}
-
-__setup("tintq=", tintq);
-
-static int imstuckcount[MAX_SMTC_VPES][8];
-/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
-static int vpemask[MAX_SMTC_VPES][8] = {
- {0, 0, 1, 0, 0, 0, 0, 1},
- {0, 0, 0, 0, 0, 0, 0, 1}
-};
-int tcnoprog[NR_CPUS];
-static atomic_t idle_hook_initialized = ATOMIC_INIT(0);
-static int clock_hang_reported[NR_CPUS];
-
-#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
-
-/*
- * Configure shared TLB - VPC configuration bit must be set by caller
- */
-
-static void smtc_configure_tlb(void)
-{
- int i, tlbsiz, vpes;
- unsigned long mvpconf0;
- unsigned long config1val;
-
- /* Set up ASID preservation table */
- for (vpes=0; vpes<MAX_SMTC_TLBS; vpes++) {
- for(i = 0; i < MAX_SMTC_ASIDS; i++) {
- smtc_live_asid[vpes][i] = 0;
- }
- }
- mvpconf0 = read_c0_mvpconf0();
-
- if ((vpes = ((mvpconf0 & MVPCONF0_PVPE)
- >> MVPCONF0_PVPE_SHIFT) + 1) > 1) {
- /* If we have multiple VPEs, try to share the TLB */
- if ((mvpconf0 & MVPCONF0_TLBS) && !nostlb) {
- /*
- * If TLB sizing is programmable, shared TLB
- * size is the total available complement.
- * Otherwise, we have to take the sum of all
- * static VPE TLB entries.
- */
- if ((tlbsiz = ((mvpconf0 & MVPCONF0_PTLBE)
- >> MVPCONF0_PTLBE_SHIFT)) == 0) {
- /*
- * If there's more than one VPE, there had better
- * be more than one TC, because we need one to bind
- * to each VPE in turn to be able to read
- * its configuration state!
- */
- settc(1);
- /* Stop the TC from doing anything foolish */
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
- /* No need to un-Halt - that happens later anyway */
- for (i=0; i < vpes; i++) {
- write_tc_c0_tcbind(i);
- /*
- * To be 100% sure we're really getting the right
- * information, we exit the configuration state
- * and do an IHB after each rebinding.
- */
- write_c0_mvpcontrol(
- read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
- mips_ihb();
- /*
- * Only count if the MMU Type indicated is TLB
- */
- if (((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {
- config1val = read_vpe_c0_config1();
- tlbsiz += ((config1val >> 25) & 0x3f) + 1;
- }
-
- /* Put core back in configuration state */
- write_c0_mvpcontrol(
- read_c0_mvpcontrol() | MVPCONTROL_VPC );
- mips_ihb();
- }
- }
- write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
- ehb();
-
- /*
- * Setup kernel data structures to use software total,
- * rather than read the per-VPE Config1 value. The values
- * for "CPU 0" gets copied to all the other CPUs as part
- * of their initialization in smtc_cpu_setup().
- */
-
- /* MIPS32 limits TLB indices to 64 */
- if (tlbsiz > 64)
- tlbsiz = 64;
- cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz;
- smtc_status |= SMTC_TLB_SHARED;
- local_flush_tlb_all();
-
- printk("TLB of %d entry pairs shared by %d VPEs\n",
- tlbsiz, vpes);
- } else {
- printk("WARNING: TLB Not Sharable on SMTC Boot!\n");
- }
- }
-}
-
-
-/*
- * Incrementally build the CPU map out of constituent MIPS MT cores,
- * using the specified available VPEs and TCs. Plaform code needs
- * to ensure that each MIPS MT core invokes this routine on reset,
- * one at a time(!).
- *
- * This version of the build_cpu_map and prepare_cpus routines assumes
- * that *all* TCs of a MIPS MT core will be used for Linux, and that
- * they will be spread across *all* available VPEs (to minimise the
- * loss of efficiency due to exception service serialization).
- * An improved version would pick up configuration information and
- * possibly leave some TCs/VPEs as "slave" processors.
- *
- * Use c0_MVPConf0 to find out how many TCs are available, setting up
- * cpu_possible_mask and the logical/physical mappings.
- */
-
-int __init smtc_build_cpu_map(int start_cpu_slot)
-{
- int i, ntcs;
-
- /*
- * The CPU map isn't actually used for anything at this point,
- * so it's not clear what else we should do apart from set
- * everything up so that "logical" = "physical".
- */
- ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
- for (i=start_cpu_slot; i<NR_CPUS && i<ntcs; i++) {
- set_cpu_possible(i, true);
- __cpu_number_map[i] = i;
- __cpu_logical_map[i] = i;
- }
-#ifdef CONFIG_MIPS_MT_FPAFF
- /* Initialize map of CPUs with FPUs */
- cpus_clear(mt_fpu_cpumask);
-#endif
-
- /* One of those TC's is the one booting, and not a secondary... */
- printk("%i available secondary CPU TC(s)\n", i - 1);
-
- return i;
-}
-
-/*
- * Common setup before any secondaries are started
- * Make sure all CPUs are in a sensible state before we boot any of the
- * secondaries.
- *
- * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly
- * as possible across the available VPEs.
- */
-
-static void smtc_tc_setup(int vpe, int tc, int cpu)
-{
- static int cp1contexts[MAX_SMTC_VPES];
-
- /*
- * Make a local copy of the available FPU contexts in order
- * to keep track of TCs that can have one.
- */
- if (tc == 1)
- {
- /*
- * FIXME: Multi-core SMTC hasn't been tested and the
- * maximum number of VPEs may change.
- */
- cp1contexts[0] = smtc_nconf1[0] - 1;
- cp1contexts[1] = smtc_nconf1[1];
- }
-
- settc(tc);
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
- write_tc_c0_tcstatus((read_tc_c0_tcstatus()
- & ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
- | TCSTATUS_A);
- /*
- * TCContext gets an offset from the base of the IPIQ array
- * to be used in low-level code to detect the presence of
- * an active IPI queue.
- */
- write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);
-
- /* Bind TC to VPE. */
- write_tc_c0_tcbind(vpe);
-
- /* In general, all TCs should have the same cpu_data indications. */
- memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
-
- /* Check to see if there is a FPU context available for this TC. */
- if (!cp1contexts[vpe])
- cpu_data[cpu].options &= ~MIPS_CPU_FPU;
- else
- cp1contexts[vpe]--;
-
- /* Store the TC and VPE into the cpu_data structure. */
- cpu_data[cpu].vpe_id = vpe;
- cpu_data[cpu].tc_id = tc;
-
- /* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */
- cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff;
-}
-
-/*
- * Tweak to get Count registers synced as closely as possible. The
- * value seems good for 34K-class cores.
- */
-
-#define CP0_SKEW 8
-
-void smtc_prepare_cpus(int cpus)
-{
- int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;
- unsigned long flags;
- unsigned long val;
- int nipi;
- struct smtc_ipi *pipi;
-
- /* disable interrupts so we can disable MT */
- local_irq_save(flags);
- /* disable MT so we can configure */
- dvpe();
- dmt();
-
- spin_lock_init(&freeIPIq.lock);
-
- /*
- * We probably don't have as many VPEs as we do SMP "CPUs",
- * but it's possible - and in any case we'll never use more!
- */
- for (i=0; i<NR_CPUS; i++) {
- IPIQ[i].head = IPIQ[i].tail = NULL;
- spin_lock_init(&IPIQ[i].lock);
- IPIQ[i].depth = 0;
- IPIQ[i].resched_flag = 0; /* No reschedules queued initially */
- }
-
- /* cpu_data index starts at zero */
- cpu = 0;
- cpu_data[cpu].vpe_id = 0;
- cpu_data[cpu].tc_id = 0;
- cpu_data[cpu].core = (read_c0_ebase() >> 1) & 0xff;
- cpu++;
-
- /* Report on boot-time options */
- mips_mt_set_cpuoptions();
- if (vpelimit > 0)
- printk("Limit of %d VPEs set\n", vpelimit);
- if (tclimit > 0)
- printk("Limit of %d TCs set\n", tclimit);
- if (nostlb) {
- printk("Shared TLB Use Inhibited - UNSAFE for Multi-VPE Operation\n");
- }
- if (asidmask)
- printk("ASID mask value override to 0x%x\n", asidmask);
-
- /* Temporary */
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
- if (hang_trig)
- printk("Logic Analyser Trigger on suspected TC hang\n");
-#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
-
- /* Put MVPE's into 'configuration state' */
- write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );
-
- val = read_c0_mvpconf0();
- nvpe = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
- if (vpelimit > 0 && nvpe > vpelimit)
- nvpe = vpelimit;
- ntc = ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
- if (ntc > NR_CPUS)
- ntc = NR_CPUS;
- if (tclimit > 0 && ntc > tclimit)
- ntc = tclimit;
- slop = ntc % nvpe;
- for (i = 0; i < nvpe; i++) {
- tcpervpe[i] = ntc / nvpe;
- if (slop) {
- if((slop - i) > 0) tcpervpe[i]++;
- }
- }
- /* Handle command line override for VPE0 */
- if (vpe0limit > ntc) vpe0limit = ntc;
- if (vpe0limit > 0) {
- int slopslop;
- if (vpe0limit < tcpervpe[0]) {
- /* Reducing TC count - distribute to others */
- slop = tcpervpe[0] - vpe0limit;
- slopslop = slop % (nvpe - 1);
- tcpervpe[0] = vpe0limit;
- for (i = 1; i < nvpe; i++) {
- tcpervpe[i] += slop / (nvpe - 1);
- if(slopslop && ((slopslop - (i - 1) > 0)))
- tcpervpe[i]++;
- }
- } else if (vpe0limit > tcpervpe[0]) {
- /* Increasing TC count - steal from others */
- slop = vpe0limit - tcpervpe[0];
- slopslop = slop % (nvpe - 1);
- tcpervpe[0] = vpe0limit;
- for (i = 1; i < nvpe; i++) {
- tcpervpe[i] -= slop / (nvpe - 1);
- if(slopslop && ((slopslop - (i - 1) > 0)))
- tcpervpe[i]--;
- }
- }
- }
-
- /* Set up shared TLB */
- smtc_configure_tlb();
-
- for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
- /* Get number of CP1 contexts for each VPE. */
- if (tc == 0)
- {
- /*
- * Do not call settc() for TC0 or the FPU context
- * value will be incorrect. Besides, we know that
- * we are TC0 anyway.
- */
- smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() &
- VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT);
- if (nvpe == 2)
- {
- settc(1);
- smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() &
- VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT);
- settc(0);
- }
- }
- if (tcpervpe[vpe] == 0)
- continue;
- if (vpe != 0)
- printk(", ");
- printk("VPE %d: TC", vpe);
- for (i = 0; i < tcpervpe[vpe]; i++) {
- /*
- * TC 0 is bound to VPE 0 at reset,
- * and is presumably executing this
- * code. Leave it alone!
- */
- if (tc != 0) {
- smtc_tc_setup(vpe, tc, cpu);
- if (vpe != 0) {
- /*
- * Set MVP bit (possibly again). Do it
- * here to catch CPUs that have no TCs
- * bound to the VPE at reset. In that
- * case, a TC must be bound to the VPE
- * before we can set VPEControl[MVP]
- */
- write_vpe_c0_vpeconf0(
- read_vpe_c0_vpeconf0() |
- VPECONF0_MVP);
- }
- cpu++;
- }
- printk(" %d", tc);
- tc++;
- }
- if (vpe != 0) {
- /*
- * Allow this VPE to control others.
- */
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() |
- VPECONF0_MVP);
-
- /*
- * Clear any stale software interrupts from VPE's Cause
- */
- write_vpe_c0_cause(0);
-
- /*
- * Clear ERL/EXL of VPEs other than 0
- * and set restricted interrupt enable/mask.
- */
- write_vpe_c0_status((read_vpe_c0_status()
- & ~(ST0_BEV | ST0_ERL | ST0_EXL | ST0_IM))
- | (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7
- | ST0_IE));
- /*
- * set config to be the same as vpe0,
- * particularly kseg0 coherency alg
- */
- write_vpe_c0_config(read_c0_config());
- /* Clear any pending timer interrupt */
- write_vpe_c0_compare(0);
- /* Propagate Config7 */
- write_vpe_c0_config7(read_c0_config7());
- write_vpe_c0_count(read_c0_count() + CP0_SKEW);
- ehb();
- }
- /* enable multi-threading within VPE */
- write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
- /* enable the VPE */
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
- }
-
- /*
- * Pull any physically present but unused TCs out of circulation.
- */
- while (tc < (((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1)) {
- set_cpu_possible(tc, false);
- set_cpu_present(tc, false);
- tc++;
- }
-
- /* release config state */
- write_c0_mvpcontrol( read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
-
- printk("\n");
-
- /* Set up coprocessor affinity CPU mask(s) */
-
-#ifdef CONFIG_MIPS_MT_FPAFF
- for (tc = 0; tc < ntc; tc++) {
- if (cpu_data[tc].options & MIPS_CPU_FPU)
- cpu_set(tc, mt_fpu_cpumask);
- }
-#endif
-
- /* set up ipi interrupts... */
-
- /* If we have multiple VPEs running, set up the cross-VPE interrupt */
-
- setup_cross_vpe_interrupts(nvpe);
-
- /* Set up queue of free IPI "messages". */
- nipi = NR_CPUS * IPIBUF_PER_CPU;
- if (ipibuffers > 0)
- nipi = ipibuffers;
-
- pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL);
- if (pipi == NULL)
- panic("kmalloc of IPI message buffers failed");
- else
- printk("IPI buffer pool of %d buffers\n", nipi);
- for (i = 0; i < nipi; i++) {
- smtc_ipi_nq(&freeIPIq, pipi);
- pipi++;
- }
-
- /* Arm multithreading and enable other VPEs - but all TCs are Halted */
- emt(EMT_ENABLE);
- evpe(EVPE_ENABLE);
- local_irq_restore(flags);
- /* Initialize SMTC /proc statistics/diagnostics */
- init_smtc_stats();
-}
-
-
-/*
- * Setup the PC, SP, and GP of a secondary processor and start it
- * running!
- * smp_bootstrap is the place to resume from
- * __KSTK_TOS(idle) is apparently the stack pointer
- * (unsigned long)idle->thread_info the gp
- *
- */
-void smtc_boot_secondary(int cpu, struct task_struct *idle)
-{
- extern u32 kernelsp[NR_CPUS];
- unsigned long flags;
- int mtflags;
-
- LOCK_MT_PRA();
- if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
- dvpe();
- }
- settc(cpu_data[cpu].tc_id);
-
- /* pc */
- write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
-
- /* stack pointer */
- kernelsp[cpu] = __KSTK_TOS(idle);
- write_tc_gpr_sp(__KSTK_TOS(idle));
-
- /* global pointer */
- write_tc_gpr_gp((unsigned long)task_thread_info(idle));
-
- smtc_status |= SMTC_MTC_ACTIVE;
- write_tc_c0_tchalt(0);
- if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
- evpe(EVPE_ENABLE);
- }
- UNLOCK_MT_PRA();
-}
-
-void smtc_init_secondary(void)
-{
-}
-
-void smtc_smp_finish(void)
-{
- int cpu = smp_processor_id();
-
- /*
- * Lowest-numbered CPU per VPE starts a clock tick.
- * Like per_cpu_trap_init() hack, this assumes that
- * SMTC init code assigns TCs consdecutively and
- * in ascending order across available VPEs.
- */
- if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id))
- write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
-
- local_irq_enable();
-
- printk("TC %d going on-line as CPU %d\n",
- cpu_data[smp_processor_id()].tc_id, smp_processor_id());
-}
-
-void smtc_cpus_done(void)
-{
-}
-
-/*
- * Support for SMTC-optimized driver IRQ registration
- */
-
-/*
- * SMTC Kernel needs to manipulate low-level CPU interrupt mask
- * in do_IRQ. These are passed in setup_irq_smtc() and stored
- * in this table.
- */
-
-int setup_irq_smtc(unsigned int irq, struct irqaction * new,
- unsigned long hwmask)
-{
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
- unsigned int vpe = current_cpu_data.vpe_id;
-
- vpemask[vpe][irq - MIPS_CPU_IRQ_BASE] = 1;
-#endif
- irq_hwmask[irq] = hwmask;
-
- return setup_irq(irq, new);
-}
-
-#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-/*
- * Support for IRQ affinity to TCs
- */
-
-void smtc_set_irq_affinity(unsigned int irq, cpumask_t affinity)
-{
- /*
- * If a "fast path" cache of quickly decodable affinity state
- * is maintained, this is where it gets done, on a call up
- * from the platform affinity code.
- */
-}
-
-void smtc_forward_irq(struct irq_data *d)
-{
- unsigned int irq = d->irq;
- int target;
-
- /*
- * OK wise guy, now figure out how to get the IRQ
- * to be serviced on an authorized "CPU".
- *
- * Ideally, to handle the situation where an IRQ has multiple
- * eligible CPUS, we would maintain state per IRQ that would
- * allow a fair distribution of service requests. Since the
- * expected use model is any-or-only-one, for simplicity
- * and efficiency, we just pick the easiest one to find.
- */
-
- target = cpumask_first(d->affinity);
-
- /*
- * We depend on the platform code to have correctly processed
- * IRQ affinity change requests to ensure that the IRQ affinity
- * mask has been purged of bits corresponding to nonexistent and
- * offline "CPUs", and to TCs bound to VPEs other than the VPE
- * connected to the physical interrupt input for the interrupt
- * in question. Otherwise we have a nasty problem with interrupt
- * mask management. This is best handled in non-performance-critical
- * platform IRQ affinity setting code, to minimize interrupt-time
- * checks.
- */
-
- /* If no one is eligible, service locally */
- if (target >= NR_CPUS)
- do_IRQ_no_affinity(irq);
- else
- smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq);
-}
-
-#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
-
-/*
- * IPI model for SMTC is tricky, because interrupts aren't TC-specific.
- * Within a VPE one TC can interrupt another by different approaches.
- * The easiest to get right would probably be to make all TCs except
- * the target IXMT and set a software interrupt, but an IXMT-based
- * scheme requires that a handler must run before a new IPI could
- * be sent, which would break the "broadcast" loops in MIPS MT.
- * A more gonzo approach within a VPE is to halt the TC, extract
- * its Restart, Status, and a couple of GPRs, and program the Restart
- * address to emulate an interrupt.
- *
- * Within a VPE, one can be confident that the target TC isn't in
- * a critical EXL state when halted, since the write to the Halt
- * register could not have issued on the writing thread if the
- * halting thread had EXL set. So k0 and k1 of the target TC
- * can be used by the injection code. Across VPEs, one can't
- * be certain that the target TC isn't in a critical exception
- * state. So we try a two-step process of sending a software
- * interrupt to the target VPE, which either handles the event
- * itself (if it was the target) or injects the event within
- * the VPE.
- */
-
-static void smtc_ipi_qdump(void)
-{
- int i;
- struct smtc_ipi *temp;
-
- for (i = 0; i < NR_CPUS ;i++) {
- pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
- i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
- IPIQ[i].depth);
- temp = IPIQ[i].head;
-
- while (temp != IPIQ[i].tail) {
- pr_debug("%d %d %d: ", temp->type, temp->dest,
- (int)temp->arg);
-#ifdef SMTC_IPI_DEBUG
- pr_debug("%u %lu\n", temp->sender, temp->stamp);
-#else
- pr_debug("\n");
-#endif
- temp = temp->flink;
- }
- }
-}
-
-/*
- * The standard atomic.h primitives don't quite do what we want
- * here: We need an atomic add-and-return-previous-value (which
- * could be done with atomic_add_return and a decrement) and an
- * atomic set/zero-and-return-previous-value (which can't really
- * be done with the atomic.h primitives). And since this is
- * MIPS MT, we can assume that we have LL/SC.
- */
-static inline int atomic_postincrement(atomic_t *v)
-{
- unsigned long result;
-
- unsigned long temp;
-
- __asm__ __volatile__(
- "1: ll %0, %2 \n"
- " addu %1, %0, 1 \n"
- " sc %1, %2 \n"
- " beqz %1, 1b \n"
- __WEAK_LLSC_MB
- : "=&r" (result), "=&r" (temp), "=m" (v->counter)
- : "m" (v->counter)
- : "memory");
-
- return result;
-}
-
-void smtc_send_ipi(int cpu, int type, unsigned int action)
-{
- int tcstatus;
- struct smtc_ipi *pipi;
- unsigned long flags;
- int mtflags;
- unsigned long tcrestart;
- int set_resched_flag = (type == LINUX_SMP_IPI &&
- action == SMP_RESCHEDULE_YOURSELF);
-
- if (cpu == smp_processor_id()) {
- printk("Cannot Send IPI to self!\n");
- return;
- }
- if (set_resched_flag && IPIQ[cpu].resched_flag != 0)
- return; /* There is a reschedule queued already */
-
- /* Set up a descriptor, to be delivered either promptly or queued */
- pipi = smtc_ipi_dq(&freeIPIq);
- if (pipi == NULL) {
- bust_spinlocks(1);
- mips_mt_regdump(dvpe());
- panic("IPI Msg. Buffers Depleted");
- }
- pipi->type = type;
- pipi->arg = (void *)action;
- pipi->dest = cpu;
- if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
- /* If not on same VPE, enqueue and send cross-VPE interrupt */
- IPIQ[cpu].resched_flag |= set_resched_flag;
- smtc_ipi_nq(&IPIQ[cpu], pipi);
- LOCK_CORE_PRA();
- settc(cpu_data[cpu].tc_id);
- write_vpe_c0_cause(read_vpe_c0_cause() | C_SW1);
- UNLOCK_CORE_PRA();
- } else {
- /*
- * Not sufficient to do a LOCK_MT_PRA (dmt) here,
- * since ASID shootdown on the other VPE may
- * collide with this operation.
- */
- LOCK_CORE_PRA();
- settc(cpu_data[cpu].tc_id);
- /* Halt the targeted TC */
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
-
- /*
- * Inspect TCStatus - if IXMT is set, we have to queue
- * a message. Otherwise, we set up the "interrupt"
- * of the other TC
- */
- tcstatus = read_tc_c0_tcstatus();
-
- if ((tcstatus & TCSTATUS_IXMT) != 0) {
- /*
- * If we're in the the irq-off version of the wait
- * loop, we need to force exit from the wait and
- * do a direct post of the IPI.
- */
- if (cpu_wait == r4k_wait_irqoff) {
- tcrestart = read_tc_c0_tcrestart();
- if (address_is_in_r4k_wait_irqoff(tcrestart)) {
- write_tc_c0_tcrestart(__pastwait);
- tcstatus &= ~TCSTATUS_IXMT;
- write_tc_c0_tcstatus(tcstatus);
- goto postdirect;
- }
- }
- /*
- * Otherwise we queue the message for the target TC
- * to pick up when he does a local_irq_restore()
- */
- write_tc_c0_tchalt(0);
- UNLOCK_CORE_PRA();
- IPIQ[cpu].resched_flag |= set_resched_flag;
- smtc_ipi_nq(&IPIQ[cpu], pipi);
- } else {
-postdirect:
- post_direct_ipi(cpu, pipi);
- write_tc_c0_tchalt(0);
- UNLOCK_CORE_PRA();
- }
- }
-}
-
-/*
- * Send IPI message to Halted TC, TargTC/TargVPE already having been set
- */
-static void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
-{
- struct pt_regs *kstack;
- unsigned long tcstatus;
- unsigned long tcrestart;
- extern u32 kernelsp[NR_CPUS];
- extern void __smtc_ipi_vector(void);
-//printk("%s: on %d for %d\n", __func__, smp_processor_id(), cpu);
-
- /* Extract Status, EPC from halted TC */
- tcstatus = read_tc_c0_tcstatus();
- tcrestart = read_tc_c0_tcrestart();
- /* If TCRestart indicates a WAIT instruction, advance the PC */
- if ((tcrestart & 0x80000000)
- && ((*(unsigned int *)tcrestart & 0xfe00003f) == 0x42000020)) {
- tcrestart += 4;
- }
- /*
- * Save on TC's future kernel stack
- *
- * CU bit of Status is indicator that TC was
- * already running on a kernel stack...
- */
- if (tcstatus & ST0_CU0) {
- /* Note that this "- 1" is pointer arithmetic */
- kstack = ((struct pt_regs *)read_tc_gpr_sp()) - 1;
- } else {
- kstack = ((struct pt_regs *)kernelsp[cpu]) - 1;
- }
-
- kstack->cp0_epc = (long)tcrestart;
- /* Save TCStatus */
- kstack->cp0_tcstatus = tcstatus;
- /* Pass token of operation to be performed kernel stack pad area */
- kstack->pad0[4] = (unsigned long)pipi;
- /* Pass address of function to be called likewise */
- kstack->pad0[5] = (unsigned long)&ipi_decode;
- /* Set interrupt exempt and kernel mode */
- tcstatus |= TCSTATUS_IXMT;
- tcstatus &= ~TCSTATUS_TKSU;
- write_tc_c0_tcstatus(tcstatus);
- ehb();
- /* Set TC Restart address to be SMTC IPI vector */
- write_tc_c0_tcrestart(__smtc_ipi_vector);
-}
-
-static void ipi_resched_interrupt(void)
-{
- scheduler_ipi();
-}
-
-static void ipi_call_interrupt(void)
-{
- /* Invoke generic function invocation code in smp.c */
- smp_call_function_interrupt();
-}
-
-DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
-
-static void __irq_entry smtc_clock_tick_interrupt(void)
-{
- unsigned int cpu = smp_processor_id();
- struct clock_event_device *cd;
- int irq = MIPS_CPU_IRQ_BASE + 1;
-
- irq_enter();
- kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
- cd = &per_cpu(mips_clockevent_device, cpu);
- cd->event_handler(cd);
- irq_exit();
-}
-
-void ipi_decode(struct smtc_ipi *pipi)
-{
- void *arg_copy = pipi->arg;
- int type_copy = pipi->type;
-
- smtc_ipi_nq(&freeIPIq, pipi);
-
- switch (type_copy) {
- case SMTC_CLOCK_TICK:
- smtc_clock_tick_interrupt();
- break;
-
- case LINUX_SMP_IPI:
- switch ((int)arg_copy) {
- case SMP_RESCHEDULE_YOURSELF:
- ipi_resched_interrupt();
- break;
- case SMP_CALL_FUNCTION:
- ipi_call_interrupt();
- break;
- default:
- printk("Impossible SMTC IPI Argument %p\n", arg_copy);
- break;
- }
- break;
-#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
- case IRQ_AFFINITY_IPI:
- /*
- * Accept a "forwarded" interrupt that was initially
- * taken by a TC who doesn't have affinity for the IRQ.
- */
- do_IRQ_no_affinity((int)arg_copy);
- break;
-#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
- default:
- printk("Impossible SMTC IPI Type 0x%x\n", type_copy);
- break;
- }
-}
-
-/*
- * Similar to smtc_ipi_replay(), but invoked from context restore,
- * so it reuses the current exception frame rather than set up a
- * new one with self_ipi.
- */
-
-void deferred_smtc_ipi(void)
-{
- int cpu = smp_processor_id();
-
- /*
- * Test is not atomic, but much faster than a dequeue,
- * and the vast majority of invocations will have a null queue.
- * If irq_disabled when this was called, then any IPIs queued
- * after we test last will be taken on the next irq_enable/restore.
- * If interrupts were enabled, then any IPIs added after the
- * last test will be taken directly.
- */
-
- while (IPIQ[cpu].head != NULL) {
- struct smtc_ipi_q *q = &IPIQ[cpu];
- struct smtc_ipi *pipi;
- unsigned long flags;
-
- /*
- * It may be possible we'll come in with interrupts
- * already enabled.
- */
- local_irq_save(flags);
- spin_lock(&q->lock);
- pipi = __smtc_ipi_dq(q);
- spin_unlock(&q->lock);
- if (pipi != NULL) {
- if (pipi->type == LINUX_SMP_IPI &&
- (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
- IPIQ[cpu].resched_flag = 0;
- ipi_decode(pipi);
- }
- /*
- * The use of the __raw_local restore isn't
- * as obviously necessary here as in smtc_ipi_replay(),
- * but it's more efficient, given that we're already
- * running down the IPI queue.
- */
- __arch_local_irq_restore(flags);
- }
-}
-
-/*
- * Cross-VPE interrupts in the SMTC prototype use "software interrupts"
- * set via cross-VPE MTTR manipulation of the Cause register. It would be
- * in some regards preferable to have external logic for "doorbell" hardware
- * interrupts.
- */
-
-static int cpu_ipi_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_IRQ;
-
-static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
-{
- int my_vpe = cpu_data[smp_processor_id()].vpe_id;
- int my_tc = cpu_data[smp_processor_id()].tc_id;
- int cpu;
- struct smtc_ipi *pipi;
- unsigned long tcstatus;
- int sent;
- unsigned long flags;
- unsigned int mtflags;
- unsigned int vpflags;
-
- /*
- * So long as cross-VPE interrupts are done via
- * MFTR/MTTR read-modify-writes of Cause, we need
- * to stop other VPEs whenever the local VPE does
- * anything similar.
- */
- local_irq_save(flags);
- vpflags = dvpe();
- clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ);
- set_c0_status(0x100 << MIPS_CPU_IPI_IRQ);
- irq_enable_hazard();
- evpe(vpflags);
- local_irq_restore(flags);
-
- /*
- * Cross-VPE Interrupt handler: Try to directly deliver IPIs
- * queued for TCs on this VPE other than the current one.
- * Return-from-interrupt should cause us to drain the queue
- * for the current TC, so we ought not to have to do it explicitly here.
- */
-
- for_each_online_cpu(cpu) {
- if (cpu_data[cpu].vpe_id != my_vpe)
- continue;
-
- pipi = smtc_ipi_dq(&IPIQ[cpu]);
- if (pipi != NULL) {
- if (cpu_data[cpu].tc_id != my_tc) {
- sent = 0;
- LOCK_MT_PRA();
- settc(cpu_data[cpu].tc_id);
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
- tcstatus = read_tc_c0_tcstatus();
- if ((tcstatus & TCSTATUS_IXMT) == 0) {
- post_direct_ipi(cpu, pipi);
- sent = 1;
- }
- write_tc_c0_tchalt(0);
- UNLOCK_MT_PRA();
- if (!sent) {
- smtc_ipi_req(&IPIQ[cpu], pipi);
- }
- } else {
- /*
- * ipi_decode() should be called
- * with interrupts off
- */
- local_irq_save(flags);
- if (pipi->type == LINUX_SMP_IPI &&
- (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
- IPIQ[cpu].resched_flag = 0;
- ipi_decode(pipi);
- local_irq_restore(flags);
- }
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static void ipi_irq_dispatch(void)
-{
- do_IRQ(cpu_ipi_irq);
-}
-
-static struct irqaction irq_ipi = {
- .handler = ipi_interrupt,
- .flags = IRQF_PERCPU,
- .name = "SMTC_IPI"
-};
-
-static void setup_cross_vpe_interrupts(unsigned int nvpe)
-{
- if (nvpe < 1)
- return;
-
- if (!cpu_has_vint)
- panic("SMTC Kernel requires Vectored Interrupt support");
-
- set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch);
-
- setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
-
- irq_set_handler(cpu_ipi_irq, handle_percpu_irq);
-}
-
-/*
- * SMTC-specific hacks invoked from elsewhere in the kernel.
- */
-
- /*
- * smtc_ipi_replay is called from raw_local_irq_restore
- */
-
-void smtc_ipi_replay(void)
-{
- unsigned int cpu = smp_processor_id();
-
- /*
- * To the extent that we've ever turned interrupts off,
- * we may have accumulated deferred IPIs. This is subtle.
- * we should be OK: If we pick up something and dispatch
- * it here, that's great. If we see nothing, but concurrent
- * with this operation, another TC sends us an IPI, IXMT
- * is clear, and we'll handle it as a real pseudo-interrupt
- * and not a pseudo-pseudo interrupt. The important thing
- * is to do the last check for queued message *after* the
- * re-enabling of interrupts.
- */
- while (IPIQ[cpu].head != NULL) {
- struct smtc_ipi_q *q = &IPIQ[cpu];
- struct smtc_ipi *pipi;
- unsigned long flags;
-
- /*
- * It's just possible we'll come in with interrupts
- * already enabled.
- */
- local_irq_save(flags);
-
- spin_lock(&q->lock);
- pipi = __smtc_ipi_dq(q);
- spin_unlock(&q->lock);
- /*
- ** But use a raw restore here to avoid recursion.
- */
- __arch_local_irq_restore(flags);
-
- if (pipi) {
- self_ipi(pipi);
- smtc_cpu_stats[cpu].selfipis++;
- }
- }
-}
-
-EXPORT_SYMBOL(smtc_ipi_replay);
-
-void smtc_idle_loop_hook(void)
-{
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
- int im;
- int flags;
- int mtflags;
- int bit;
- int vpe;
- int tc;
- int hook_ntcs;
- /*
- * printk within DMT-protected regions can deadlock,
- * so buffer diagnostic messages for later output.
- */
- char *pdb_msg;
- char id_ho_db_msg[768]; /* worst-case use should be less than 700 */
-
- if (atomic_read(&idle_hook_initialized) == 0) { /* fast test */
- if (atomic_add_return(1, &idle_hook_initialized) == 1) {
- int mvpconf0;
- /* Tedious stuff to just do once */
- mvpconf0 = read_c0_mvpconf0();
- hook_ntcs = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
- if (hook_ntcs > NR_CPUS)
- hook_ntcs = NR_CPUS;
- for (tc = 0; tc < hook_ntcs; tc++) {
- tcnoprog[tc] = 0;
- clock_hang_reported[tc] = 0;
- }
- for (vpe = 0; vpe < 2; vpe++)
- for (im = 0; im < 8; im++)
- imstuckcount[vpe][im] = 0;
- printk("Idle loop test hook initialized for %d TCs\n", hook_ntcs);
- atomic_set(&idle_hook_initialized, 1000);
- } else {
- /* Someone else is initializing in parallel - let 'em finish */
- while (atomic_read(&idle_hook_initialized) < 1000)
- ;
- }
- }
-
- /* Have we stupidly left IXMT set somewhere? */
- if (read_c0_tcstatus() & 0x400) {
- write_c0_tcstatus(read_c0_tcstatus() & ~0x400);
- ehb();
- printk("Dangling IXMT in cpu_idle()\n");
- }
-
- /* Have we stupidly left an IM bit turned off? */
-#define IM_LIMIT 2000
- local_irq_save(flags);
- mtflags = dmt();
- pdb_msg = &id_ho_db_msg[0];
- im = read_c0_status();
- vpe = current_cpu_data.vpe_id;
- for (bit = 0; bit < 8; bit++) {
- /*
- * In current prototype, I/O interrupts
- * are masked for VPE > 0
- */
- if (vpemask[vpe][bit]) {
- if (!(im & (0x100 << bit)))
- imstuckcount[vpe][bit]++;
- else
- imstuckcount[vpe][bit] = 0;
- if (imstuckcount[vpe][bit] > IM_LIMIT) {
- set_c0_status(0x100 << bit);
- ehb();
- imstuckcount[vpe][bit] = 0;
- pdb_msg += sprintf(pdb_msg,
- "Dangling IM %d fixed for VPE %d\n", bit,
- vpe);
- }
- }
- }
-
- emt(mtflags);
- local_irq_restore(flags);
- if (pdb_msg != &id_ho_db_msg[0])
- printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
-#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
-
- smtc_ipi_replay();
-}
-
-void smtc_soft_dump(void)
-{
- int i;
-
- printk("Counter Interrupts taken per CPU (TC)\n");
- for (i=0; i < NR_CPUS; i++) {
- printk("%d: %ld\n", i, smtc_cpu_stats[i].timerints);
- }
- printk("Self-IPI invocations:\n");
- for (i=0; i < NR_CPUS; i++) {
- printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
- }
- smtc_ipi_qdump();
- printk("%d Recoveries of \"stolen\" FPU\n",
- atomic_read(&smtc_fpu_recoveries));
-}
-
-
-/*
- * TLB management routines special to SMTC
- */
-
-void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
-{
- unsigned long flags, mtflags, tcstat, prevhalt, asid;
- int tlb, i;
-
- /*
- * It would be nice to be able to use a spinlock here,
- * but this is invoked from within TLB flush routines
- * that protect themselves with DVPE, so if a lock is
- * held by another TC, it'll never be freed.
- *
- * DVPE/DMT must not be done with interrupts enabled,
- * so even so most callers will already have disabled
- * them, let's be really careful...
- */
-
- local_irq_save(flags);
- if (smtc_status & SMTC_TLB_SHARED) {
- mtflags = dvpe();
- tlb = 0;
- } else {
- mtflags = dmt();
- tlb = cpu_data[cpu].vpe_id;
- }
- asid = asid_cache(cpu);
-
- do {
- if (!((asid += ASID_INC) & ASID_MASK) ) {
- if (cpu_has_vtag_icache)
- flush_icache_all();
- /* Traverse all online CPUs (hack requires contiguous range) */
- for_each_online_cpu(i) {
- /*
- * We don't need to worry about our own CPU, nor those of
- * CPUs who don't share our TLB.
- */
- if ((i != smp_processor_id()) &&
- ((smtc_status & SMTC_TLB_SHARED) ||
- (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))) {
- settc(cpu_data[i].tc_id);
- prevhalt = read_tc_c0_tchalt() & TCHALT_H;
- if (!prevhalt) {
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
- }
- tcstat = read_tc_c0_tcstatus();
- smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i);
- if (!prevhalt)
- write_tc_c0_tchalt(0);
- }
- }
- if (!asid) /* fix version if needed */
- asid = ASID_FIRST_VERSION;
- local_flush_tlb_all(); /* start new asid cycle */
- }
- } while (smtc_live_asid[tlb][(asid & ASID_MASK)]);
-
- /*
- * SMTC shares the TLB within VPEs and possibly across all VPEs.
- */
- for_each_online_cpu(i) {
- if ((smtc_status & SMTC_TLB_SHARED) ||
- (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
- cpu_context(i, mm) = asid_cache(i) = asid;
- }
-
- if (smtc_status & SMTC_TLB_SHARED)
- evpe(mtflags);
- else
- emt(mtflags);
- local_irq_restore(flags);
-}
-
-/*
- * Invoked from macros defined in mmu_context.h
- * which must already have disabled interrupts
- * and done a DVPE or DMT as appropriate.
- */
-
-void smtc_flush_tlb_asid(unsigned long asid)
-{
- int entry;
- unsigned long ehi;
-
- entry = read_c0_wired();
-
- /* Traverse all non-wired entries */
- while (entry < current_cpu_data.tlbsize) {
- write_c0_index(entry);
- ehb();
- tlb_read();
- ehb();
- ehi = read_c0_entryhi();
- if ((ehi & ASID_MASK) == asid) {
- /*
- * Invalidate only entries with specified ASID,
- * makiing sure all entries differ.
- */
- write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
- write_c0_entrylo0(0);
- write_c0_entrylo1(0);
- mtc0_tlbw_hazard();
- tlb_write_indexed();
- }
- entry++;
- }
- write_c0_index(PARKED_INDEX);
- tlbw_use_hazard();
-}
-
-/*
- * Support for single-threading cache flush operations.
- */
-
-static int halt_state_save[NR_CPUS];
-
-/*
- * To really, really be sure that nothing is being done
- * by other TCs, halt them all. This code assumes that
- * a DVPE has already been done, so while their Halted
- * state is theoretically architecturally unstable, in
- * practice, it's not going to change while we're looking
- * at it.
- */
-
-void smtc_cflush_lockdown(void)
-{
- int cpu;
-
- for_each_online_cpu(cpu) {
- if (cpu != smp_processor_id()) {
- settc(cpu_data[cpu].tc_id);
- halt_state_save[cpu] = read_tc_c0_tchalt();
- write_tc_c0_tchalt(TCHALT_H);
- }
- }
- mips_ihb();
-}
-
-/* It would be cheating to change the cpu_online states during a flush! */
-
-void smtc_cflush_release(void)
-{
- int cpu;
-
- /*
- * Start with a hazard barrier to ensure
- * that all CACHE ops have played through.
- */
- mips_ihb();
-
- for_each_online_cpu(cpu) {
- if (cpu != smp_processor_id()) {
- settc(cpu_data[cpu].tc_id);
- write_tc_c0_tchalt(halt_state_save[cpu]);
- }
- }
- mips_ihb();
-}
diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
index 93f86817f20..67f2495def1 100644
--- a/arch/mips/kernel/spram.c
+++ b/arch/mips/kernel/spram.c
@@ -8,7 +8,6 @@
*
* Copyright (C) 2007, 2008 MIPS Technologies, Inc.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/stddef.h>
@@ -198,14 +197,17 @@ static void probe_spram(char *type,
}
void spram_config(void)
{
- struct cpuinfo_mips *c = &current_cpu_data;
unsigned int config0;
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_24K:
case CPU_34K:
case CPU_74K:
case CPU_1004K:
+ case CPU_1074K:
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ case CPU_P5600:
config0 = read_c0_config();
/* FIXME: addresses are Malta specific */
if (config0 & (1<<24)) {
diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
index 84536bf4a15..2242bdd4370 100644
--- a/arch/mips/kernel/sync-r4k.c
+++ b/arch/mips/kernel/sync-r4k.c
@@ -6,12 +6,9 @@
* not have done anything significant (but they may have had interrupts
* enabled briefly - prom_smp_finish() should not be responsible for enabling
* interrupts...)
- *
- * FIXME: broken for SMTC
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/irqflags.h>
#include <linux/cpumask.h>
@@ -34,14 +31,6 @@ void synchronise_count_master(int cpu)
unsigned long flags;
unsigned int initcount;
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC needs to synchronise per VPE, not per CPU
- * ignore for now
- */
- return;
-#endif
-
printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu);
local_irq_save(flags);
@@ -111,14 +100,6 @@ void synchronise_count_slave(int cpu)
int i;
unsigned int initcount;
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC needs to synchronise per VPE, not per CPU
- * ignore for now
- */
- return;
-#endif
-
/*
* Not every cpu is online at the time this gets called,
* so we first wait for the master to say everyone is ready
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index b79d13f95bf..4a4f9dda565 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -110,7 +110,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
if (cpu_has_llsc && R10000_LLSC_WAR) {
__asm__ __volatile__ (
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" li %[err], 0 \n"
"1: ll %[old], (%[addr]) \n"
" move %[tmp], %[new] \n"
@@ -135,7 +135,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
: "memory");
} else if (cpu_has_llsc) {
__asm__ __volatile__ (
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" li %[err], 0 \n"
"1: ll %[old], (%[addr]) \n"
" move %[tmp], %[new] \n"
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 364d26ae421..8d0170969e2 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -24,8 +24,8 @@
#include <linux/export.h>
#include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
#include <asm/div64.h>
-#include <asm/smtc_ipi.h>
#include <asm/time.h>
/*
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index aec3408edd4..51706d6dd5b 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -10,10 +10,12 @@
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki
* Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2014, Imagination Technologies Ltd.
*/
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/context_tracking.h>
+#include <linux/cpu_pm.h>
#include <linux/kexec.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -39,6 +41,7 @@
#include <asm/break.h>
#include <asm/cop2.h>
#include <asm/cpu.h>
+#include <asm/cpu-type.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/fpu_emulator.h>
@@ -46,6 +49,7 @@
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/module.h>
+#include <asm/msa.h>
#include <asm/pgtable.h>
#include <asm/ptrace.h>
#include <asm/sections.h>
@@ -76,7 +80,10 @@ extern asmlinkage void handle_ri_rdhwr(void);
extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
+extern asmlinkage void handle_msa_fpe(void);
extern asmlinkage void handle_fpe(void);
+extern asmlinkage void handle_ftlb(void);
+extern asmlinkage void handle_msa(void);
extern asmlinkage void handle_mdmx(void);
extern asmlinkage void handle_watch(void);
extern asmlinkage void handle_mt(void);
@@ -329,6 +336,7 @@ void show_regs(struct pt_regs *regs)
void show_registers(struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
+ mm_segment_t old_fs = get_fs();
__show_regs(regs);
print_modules();
@@ -343,9 +351,13 @@ void show_registers(struct pt_regs *regs)
printk("*HwTLS: %0*lx\n", field, tls);
}
+ if (!user_mode(regs))
+ /* Necessary for getting the correct stack content */
+ set_fs(KERNEL_DS);
show_stacktrace(current, regs);
show_code((unsigned int __user *) regs->cp0_epc);
printk("\n");
+ set_fs(old_fs);
}
static int regs_to_trapnr(struct pt_regs *regs)
@@ -359,24 +371,16 @@ void __noreturn die(const char *str, struct pt_regs *regs)
{
static int die_counter;
int sig = SIGSEGV;
-#ifdef CONFIG_MIPS_MT_SMTC
- unsigned long dvpret;
-#endif /* CONFIG_MIPS_MT_SMTC */
oops_enter();
- if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
+ if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs),
+ SIGSEGV) == NOTIFY_STOP)
sig = 0;
console_verbose();
raw_spin_lock_irq(&die_lock);
-#ifdef CONFIG_MIPS_MT_SMTC
- dvpret = dvpe();
-#endif /* CONFIG_MIPS_MT_SMTC */
bust_spinlocks(1);
-#ifdef CONFIG_MIPS_MT_SMTC
- mips_mt_regdump(dvpret);
-#endif /* CONFIG_MIPS_MT_SMTC */
printk("%s[#%d]:\n", str, ++die_counter);
show_registers(regs);
@@ -456,8 +460,8 @@ 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), SIGBUS)
- == NOTIFY_STOP)
+ if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs),
+ SIGBUS) == NOTIFY_STOP)
goto out;
die_if_kernel("Oops", regs);
@@ -622,7 +626,7 @@ static int simulate_rdhwr(struct pt_regs *regs, int rd, int rt)
regs->regs[rt] = read_c0_count();
return 0;
case 3: /* Count register resolution */
- switch (current_cpu_data.cputype) {
+ switch (current_cpu_type()) {
case CPU_20KC:
case CPU_25KF:
regs->regs[rt] = 1;
@@ -700,10 +704,12 @@ int process_fpemu_return(int sig, void __user *fault_addr)
si.si_addr = fault_addr;
si.si_signo = sig;
if (sig == SIGSEGV) {
+ down_read(&current->mm->mmap_sem);
if (find_vma(current->mm, (unsigned long)fault_addr))
si.si_code = SEGV_ACCERR;
else
si.si_code = SEGV_MAPERR;
+ up_read(&current->mm->mmap_sem);
} else {
si.si_code = BUS_ADRERR;
}
@@ -726,8 +732,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
siginfo_t info = {0};
prev_state = exception_enter();
- if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
- == NOTIFY_STOP)
+ if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs),
+ SIGFPE) == NOTIFY_STOP)
goto out;
die_if_kernel("FP exception in kernel code", regs);
@@ -797,7 +803,8 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
return;
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
- if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+ if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs),
+ SIGTRAP) == NOTIFY_STOP)
return;
/*
@@ -852,6 +859,11 @@ asmlinkage void do_bp(struct pt_regs *regs)
enum ctx_state prev_state;
unsigned long epc;
u16 instr[2];
+ mm_segment_t seg;
+
+ seg = get_fs();
+ if (!user_mode(regs))
+ set_fs(KERNEL_DS);
prev_state = exception_enter();
if (get_isa16_mode(regs->cp0_epc)) {
@@ -861,17 +873,19 @@ asmlinkage void do_bp(struct pt_regs *regs)
if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) ||
(__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))))
goto out_sigsegv;
- opcode = (instr[0] << 16) | instr[1];
+ opcode = (instr[0] << 16) | instr[1];
} else {
- /* MIPS16e mode */
- if (__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)))
+ /* MIPS16e mode */
+ if (__get_user(instr[0],
+ (u16 __user *)msk_isa16_mode(epc)))
goto out_sigsegv;
- bcode = (instr[0] >> 6) & 0x3f;
- do_trap_or_bp(regs, bcode, "Break");
- goto out;
+ bcode = (instr[0] >> 6) & 0x3f;
+ do_trap_or_bp(regs, bcode, "Break");
+ goto out;
}
} else {
- if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
+ if (__get_user(opcode,
+ (unsigned int __user *) exception_epc(regs)))
goto out_sigsegv;
}
@@ -891,12 +905,14 @@ asmlinkage void do_bp(struct pt_regs *regs)
*/
switch (bcode) {
case BRK_KPROBE_BP:
- if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+ if (notify_die(DIE_BREAK, "debug", regs, bcode,
+ regs_to_trapnr(regs), 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)
+ if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode,
+ regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
goto out;
else
break;
@@ -907,6 +923,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
do_trap_or_bp(regs, bcode, "Break");
out:
+ set_fs(seg);
exception_exit(prev_state);
return;
@@ -920,8 +937,13 @@ asmlinkage void do_tr(struct pt_regs *regs)
u32 opcode, tcode = 0;
enum ctx_state prev_state;
u16 instr[2];
+ mm_segment_t seg;
unsigned long epc = msk_isa16_mode(exception_epc(regs));
+ seg = get_fs();
+ if (!user_mode(regs))
+ set_fs(get_ds());
+
prev_state = exception_enter();
if (get_isa16_mode(regs->cp0_epc)) {
if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
@@ -942,6 +964,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
do_trap_or_bp(regs, tcode, "Trap");
out:
+ set_fs(seg);
exception_exit(prev_state);
return;
@@ -960,8 +983,8 @@ asmlinkage void do_ri(struct pt_regs *regs)
int status = -1;
prev_state = exception_enter();
- if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL)
- == NOTIFY_STOP)
+ if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
+ SIGILL) == NOTIFY_STOP)
goto out;
die_if_kernel("Reserved instruction in kernel code", regs);
@@ -1063,6 +1086,76 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
return NOTIFY_OK;
}
+static int enable_restore_fp_context(int msa)
+{
+ int err, was_fpu_owner;
+
+ if (!used_math()) {
+ /* First time FP context user. */
+ err = init_fpu();
+ if (msa && !err)
+ enable_msa();
+ if (!err)
+ set_used_math();
+ return err;
+ }
+
+ /*
+ * This task has formerly used the FP context.
+ *
+ * If this thread has no live MSA vector context then we can simply
+ * restore the scalar FP context. If it has live MSA vector context
+ * (that is, it has or may have used MSA since last performing a
+ * function call) then we'll need to restore the vector context. This
+ * applies even if we're currently only executing a scalar FP
+ * instruction. This is because if we were to later execute an MSA
+ * instruction then we'd either have to:
+ *
+ * - Restore the vector context & clobber any registers modified by
+ * scalar FP instructions between now & then.
+ *
+ * or
+ *
+ * - Not restore the vector context & lose the most significant bits
+ * of all vector registers.
+ *
+ * Neither of those options is acceptable. We cannot restore the least
+ * significant bits of the registers now & only restore the most
+ * significant bits later because the most significant bits of any
+ * vector registers whose aliased FP register is modified now will have
+ * been zeroed. We'd have no way to know that when restoring the vector
+ * context & thus may load an outdated value for the most significant
+ * bits of a vector register.
+ */
+ if (!msa && !thread_msa_context_live())
+ return own_fpu(1);
+
+ /*
+ * This task is using or has previously used MSA. Thus we require
+ * that Status.FR == 1.
+ */
+ was_fpu_owner = is_fpu_owner();
+ err = own_fpu(0);
+ if (err)
+ return err;
+
+ enable_msa();
+ write_msa_csr(current->thread.fpu.msacsr);
+ set_thread_flag(TIF_USEDMSA);
+
+ /*
+ * If this is the first time that the task is using MSA and it has
+ * previously used scalar FP in this time slice then we already nave
+ * FP context which we shouldn't clobber.
+ */
+ if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
+ return 0;
+
+ /* We need to restore the vector context. */
+ restore_msa(current);
+ return 0;
+}
+
asmlinkage void do_cpu(struct pt_regs *regs)
{
enum ctx_state prev_state;
@@ -1070,7 +1163,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
unsigned long old_epc, old31;
unsigned int opcode;
unsigned int cpid;
- int status;
+ int status, err;
unsigned long __maybe_unused flags;
prev_state = exception_enter();
@@ -1142,20 +1235,15 @@ asmlinkage void do_cpu(struct pt_regs *regs)
/* Fall through. */
case 1:
- if (used_math()) /* Using the FPU again. */
- own_fpu(1);
- else { /* First time FPU user. */
- init_fpu();
- set_used_math();
- }
+ err = enable_restore_fp_context(0);
- if (!raw_cpu_has_fpu) {
+ if (!raw_cpu_has_fpu || err) {
int sig;
void __user *fault_addr = NULL;
sig = fpu_emulator_cop1Handler(regs,
&current->thread.fpu,
0, &fault_addr);
- if (!process_fpemu_return(sig, fault_addr))
+ if (!process_fpemu_return(sig, fault_addr) && !err)
mt_ase_fp_affinity();
}
@@ -1172,6 +1260,37 @@ out:
exception_exit(prev_state);
}
+asmlinkage void do_msa_fpe(struct pt_regs *regs)
+{
+ enum ctx_state prev_state;
+
+ prev_state = exception_enter();
+ die_if_kernel("do_msa_fpe invoked from kernel context!", regs);
+ force_sig(SIGFPE, current);
+ exception_exit(prev_state);
+}
+
+asmlinkage void do_msa(struct pt_regs *regs)
+{
+ enum ctx_state prev_state;
+ int err;
+
+ prev_state = exception_enter();
+
+ if (!cpu_has_msa || test_thread_flag(TIF_32BIT_FPREGS)) {
+ force_sig(SIGILL, current);
+ goto out;
+ }
+
+ die_if_kernel("do_msa invoked from kernel context!", regs);
+
+ err = enable_restore_fp_context(1);
+ if (err)
+ force_sig(SIGILL, current);
+out:
+ exception_exit(prev_state);
+}
+
asmlinkage void do_mdmx(struct pt_regs *regs)
{
enum ctx_state prev_state;
@@ -1326,6 +1445,10 @@ static inline void parity_protection_init(void)
case CPU_34K:
case CPU_74K:
case CPU_1004K:
+ case CPU_1074K:
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ case CPU_P5600:
{
#define ERRCTL_PE 0x80000000
#define ERRCTL_L2P 0x00800000
@@ -1415,14 +1538,27 @@ asmlinkage void cache_parity_error(void)
printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n",
reg_val & (1<<30) ? "secondary" : "primary",
reg_val & (1<<31) ? "data" : "insn");
- printk("Error bits: %s%s%s%s%s%s%s\n",
- reg_val & (1<<29) ? "ED " : "",
- reg_val & (1<<28) ? "ET " : "",
- reg_val & (1<<26) ? "EE " : "",
- reg_val & (1<<25) ? "EB " : "",
- reg_val & (1<<24) ? "EI " : "",
- reg_val & (1<<23) ? "E1 " : "",
- reg_val & (1<<22) ? "E0 " : "");
+ if (cpu_has_mips_r2 &&
+ ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
+ pr_err("Error bits: %s%s%s%s%s%s%s%s\n",
+ reg_val & (1<<29) ? "ED " : "",
+ reg_val & (1<<28) ? "ET " : "",
+ reg_val & (1<<27) ? "ES " : "",
+ reg_val & (1<<26) ? "EE " : "",
+ reg_val & (1<<25) ? "EB " : "",
+ reg_val & (1<<24) ? "EI " : "",
+ reg_val & (1<<23) ? "E1 " : "",
+ reg_val & (1<<22) ? "E0 " : "");
+ } else {
+ pr_err("Error bits: %s%s%s%s%s%s%s\n",
+ reg_val & (1<<29) ? "ED " : "",
+ reg_val & (1<<28) ? "ET " : "",
+ reg_val & (1<<26) ? "EE " : "",
+ reg_val & (1<<25) ? "EB " : "",
+ reg_val & (1<<24) ? "EI " : "",
+ reg_val & (1<<23) ? "E1 " : "",
+ reg_val & (1<<22) ? "E0 " : "");
+ }
printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1));
#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
@@ -1436,6 +1572,34 @@ asmlinkage void cache_parity_error(void)
panic("Can't handle the cache error!");
}
+asmlinkage void do_ftlb(void)
+{
+ const int field = 2 * sizeof(unsigned long);
+ unsigned int reg_val;
+
+ /* For the moment, report the problem and hang. */
+ if (cpu_has_mips_r2 &&
+ ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
+ pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
+ read_c0_ecc());
+ pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
+ reg_val = read_c0_cacheerr();
+ pr_err("c0_cacheerr == %08x\n", reg_val);
+
+ if ((reg_val & 0xc0000000) == 0xc0000000) {
+ pr_err("Decoded c0_cacheerr: FTLB parity error\n");
+ } else {
+ pr_err("Decoded c0_cacheerr: %s cache fault in %s reference.\n",
+ reg_val & (1<<30) ? "secondary" : "primary",
+ reg_val & (1<<31) ? "data" : "insn");
+ }
+ } else {
+ pr_err("FTLB error exception\n");
+ }
+ /* Just print the cacheerr bits for now */
+ cache_parity_error();
+}
+
/*
* SDBBP EJTAG debug exception handler.
* We skip the instruction and return to the next instruction.
@@ -1487,10 +1651,14 @@ int register_nmi_notifier(struct notifier_block *nb)
void __noreturn nmi_exception_handler(struct pt_regs *regs)
{
+ char str[100];
+
raw_notifier_call_chain(&nmi_chain, 0, regs);
bust_spinlocks(1);
- printk("NMI taken!!!!\n");
- die("NMI", regs);
+ 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);
}
#define VECTORSPACING 0x100 /* for EI/VI mode */
@@ -1553,7 +1721,6 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
unsigned char *b;
BUG_ON(!cpu_has_veic && !cpu_has_vint);
- BUG_ON((n < 0) && (n > 9));
if (addr == NULL) {
handler = (unsigned long) do_default_vi;
@@ -1586,19 +1753,6 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
extern char rollback_except_vec_vi;
char *vec_start = using_rollback_handler() ?
&rollback_except_vec_vi : &except_vec_vi;
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * We need to provide the SMTC vectored interrupt handler
- * not only with the address of the handler, but with the
- * Status.IM bit to be masked before going there.
- */
- extern char except_vec_vi_mori;
-#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
- const int mori_offset = &except_vec_vi_mori - vec_start + 2;
-#else
- const int mori_offset = &except_vec_vi_mori - vec_start;
-#endif
-#endif /* CONFIG_MIPS_MT_SMTC */
#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
const int lui_offset = &except_vec_vi_lui - vec_start + 2;
const int ori_offset = &except_vec_vi_ori - vec_start + 2;
@@ -1622,12 +1776,6 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
#else
handler_len);
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
- BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
-
- h = (u16 *)(b + mori_offset);
- *h = (0x100 << n);
-#endif /* CONFIG_MIPS_MT_SMTC */
h = (u16 *)(b + lui_offset);
*h = (handler >> 16) & 0xffff;
h = (u16 *)(b + ori_offset);
@@ -1692,32 +1840,16 @@ static int __init ulri_disable(char *s)
}
__setup("noulri", ulri_disable);
-void per_cpu_trap_init(bool is_boot_cpu)
+/* configure STATUS register */
+static void configure_status(void)
{
- unsigned int cpu = smp_processor_id();
- unsigned int status_set = ST0_CU0;
- unsigned int hwrena = cpu_hwrena_impl_bits;
-#ifdef CONFIG_MIPS_MT_SMTC
- int secondaryTC = 0;
- int bootTC = (cpu == 0);
-
- /*
- * Only do per_cpu_trap_init() for first TC of Each VPE.
- * Note that this hack assumes that the SMTC init code
- * assigns TCs consecutively and in ascending order.
- */
-
- if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
- ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id))
- secondaryTC = 1;
-#endif /* CONFIG_MIPS_MT_SMTC */
-
/*
* Disable coprocessors and select 32-bit or 64-bit addressing
* and the 16/32 or 32/32 FPR register model. Reset the BEV
* flag that some firmware may have left set and the TS bit (for
* IP27). Set XX for ISA IV code to work.
*/
+ unsigned int status_set = ST0_CU0;
#ifdef CONFIG_64BIT
status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
#endif
@@ -1728,6 +1860,12 @@ void per_cpu_trap_init(bool is_boot_cpu)
change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
status_set);
+}
+
+/* configure HWRENA register */
+static void configure_hwrena(void)
+{
+ unsigned int hwrena = cpu_hwrena_impl_bits;
if (cpu_has_mips_r2)
hwrena |= 0x0000000f;
@@ -1737,11 +1875,10 @@ void per_cpu_trap_init(bool is_boot_cpu)
if (hwrena)
write_c0_hwrena(hwrena);
+}
-#ifdef CONFIG_MIPS_MT_SMTC
- if (!secondaryTC) {
-#endif /* CONFIG_MIPS_MT_SMTC */
-
+static void configure_exception_vector(void)
+{
if (cpu_has_veic || cpu_has_vint) {
unsigned long sr = set_c0_status(ST0_BEV);
write_c0_ebase(ebase);
@@ -1757,6 +1894,16 @@ void per_cpu_trap_init(bool is_boot_cpu)
} else
set_c0_cause(CAUSEF_IV);
}
+}
+
+void per_cpu_trap_init(bool is_boot_cpu)
+{
+ unsigned int cpu = smp_processor_id();
+
+ configure_status();
+ configure_hwrena();
+
+ configure_exception_vector();
/*
* Before R2 both interrupt numbers were fixed to 7, so on R2 only:
@@ -1776,10 +1923,6 @@ void per_cpu_trap_init(bool is_boot_cpu)
cp0_perfcount_irq = -1;
}
-#ifdef CONFIG_MIPS_MT_SMTC
- }
-#endif /* CONFIG_MIPS_MT_SMTC */
-
if (!cpu_data[cpu].asid_cache)
cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
@@ -1788,23 +1931,10 @@ void per_cpu_trap_init(bool is_boot_cpu)
BUG_ON(current->mm);
enter_lazy_tlb(&init_mm, current);
-#ifdef CONFIG_MIPS_MT_SMTC
- if (bootTC) {
-#endif /* CONFIG_MIPS_MT_SMTC */
/* Boot CPU's cache setup in setup_arch(). */
if (!is_boot_cpu)
cpu_cache_init();
tlb_init();
-#ifdef CONFIG_MIPS_MT_SMTC
- } else if (!secondaryTC) {
- /*
- * First TC in non-boot VPE must do subset of tlb_init()
- * for MMU countrol registers.
- */
- write_c0_pagemask(PM_DEFAULT_MASK);
- write_c0_wired(0);
- }
-#endif /* CONFIG_MIPS_MT_SMTC */
TLBMISS_HANDLER_SETUP();
}
@@ -1960,6 +2090,7 @@ void __init trap_init(void)
set_except_vector(11, handle_cpu);
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
+ set_except_vector(14, handle_msa_fpe);
if (current_cpu_type() == CPU_R6000 ||
current_cpu_type() == CPU_R6000A) {
@@ -1982,6 +2113,8 @@ void __init trap_init(void)
if (cpu_has_fpu && !cpu_has_nofpuex)
set_except_vector(15, handle_fpe);
+ set_except_vector(16, handle_ftlb);
+ set_except_vector(21, handle_msa);
set_except_vector(22, handle_mdmx);
if (cpu_has_mcheck)
@@ -2009,3 +2142,32 @@ void __init trap_init(void)
cu2_notifier(default_cu2_call, 0x80000000); /* Run last */
}
+
+static int trap_pm_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ configure_status();
+ configure_hwrena();
+ configure_exception_vector();
+
+ /* Restore register with CPU number for TLB handlers */
+ TLBMISS_HANDLER_RESTORE();
+
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block trap_pm_notifier_block = {
+ .notifier_call = trap_pm_notifier,
+};
+
+static int __init trap_pm_init(void)
+{
+ return cpu_pm_register_notifier(&trap_pm_notifier_block);
+}
+arch_initcall(trap_pm_init);
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index c369a5d3552..2b3517214d6 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -7,6 +7,7 @@
*
* Copyright (C) 1996, 1998, 1999, 2002 by Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2014 Imagination Technologies Ltd.
*
* This file contains exception handler for address error exception with the
* special capability to execute faulting instructions in software. The
@@ -110,8 +111,8 @@ extern void show_registers(struct pt_regs *regs);
#ifdef __BIG_ENDIAN
#define LoadHW(addr, value, res) \
__asm__ __volatile__ (".set\tnoat\n" \
- "1:\tlb\t%0, 0(%2)\n" \
- "2:\tlbu\t$1, 1(%2)\n\t" \
+ "1:\t"user_lb("%0", "0(%2)")"\n" \
+ "2:\t"user_lbu("$1", "1(%2)")"\n\t" \
"sll\t%0, 0x8\n\t" \
"or\t%0, $1\n\t" \
"li\t%1, 0\n" \
@@ -130,8 +131,8 @@ extern void show_registers(struct pt_regs *regs);
#define LoadW(addr, value, res) \
__asm__ __volatile__ ( \
- "1:\tlwl\t%0, (%2)\n" \
- "2:\tlwr\t%0, 3(%2)\n\t" \
+ "1:\t"user_lwl("%0", "(%2)")"\n" \
+ "2:\t"user_lwr("%0", "3(%2)")"\n\t" \
"li\t%1, 0\n" \
"3:\n\t" \
".insn\n\t" \
@@ -149,8 +150,8 @@ extern void show_registers(struct pt_regs *regs);
#define LoadHWU(addr, value, res) \
__asm__ __volatile__ ( \
".set\tnoat\n" \
- "1:\tlbu\t%0, 0(%2)\n" \
- "2:\tlbu\t$1, 1(%2)\n\t" \
+ "1:\t"user_lbu("%0", "0(%2)")"\n" \
+ "2:\t"user_lbu("$1", "1(%2)")"\n\t" \
"sll\t%0, 0x8\n\t" \
"or\t%0, $1\n\t" \
"li\t%1, 0\n" \
@@ -170,8 +171,8 @@ extern void show_registers(struct pt_regs *regs);
#define LoadWU(addr, value, res) \
__asm__ __volatile__ ( \
- "1:\tlwl\t%0, (%2)\n" \
- "2:\tlwr\t%0, 3(%2)\n\t" \
+ "1:\t"user_lwl("%0", "(%2)")"\n" \
+ "2:\t"user_lwr("%0", "3(%2)")"\n\t" \
"dsll\t%0, %0, 32\n\t" \
"dsrl\t%0, %0, 32\n\t" \
"li\t%1, 0\n" \
@@ -209,9 +210,9 @@ extern void show_registers(struct pt_regs *regs);
#define StoreHW(addr, value, res) \
__asm__ __volatile__ ( \
".set\tnoat\n" \
- "1:\tsb\t%1, 1(%2)\n\t" \
+ "1:\t"user_sb("%1", "1(%2)")"\n" \
"srl\t$1, %1, 0x8\n" \
- "2:\tsb\t$1, 0(%2)\n\t" \
+ "2:\t"user_sb("$1", "0(%2)")"\n" \
".set\tat\n\t" \
"li\t%0, 0\n" \
"3:\n\t" \
@@ -229,8 +230,8 @@ extern void show_registers(struct pt_regs *regs);
#define StoreW(addr, value, res) \
__asm__ __volatile__ ( \
- "1:\tswl\t%1,(%2)\n" \
- "2:\tswr\t%1, 3(%2)\n\t" \
+ "1:\t"user_swl("%1", "(%2)")"\n" \
+ "2:\t"user_swr("%1", "3(%2)")"\n\t" \
"li\t%0, 0\n" \
"3:\n\t" \
".insn\n\t" \
@@ -267,8 +268,8 @@ extern void show_registers(struct pt_regs *regs);
#ifdef __LITTLE_ENDIAN
#define LoadHW(addr, value, res) \
__asm__ __volatile__ (".set\tnoat\n" \
- "1:\tlb\t%0, 1(%2)\n" \
- "2:\tlbu\t$1, 0(%2)\n\t" \
+ "1:\t"user_lb("%0", "1(%2)")"\n" \
+ "2:\t"user_lbu("$1", "0(%2)")"\n\t" \
"sll\t%0, 0x8\n\t" \
"or\t%0, $1\n\t" \
"li\t%1, 0\n" \
@@ -287,8 +288,8 @@ extern void show_registers(struct pt_regs *regs);
#define LoadW(addr, value, res) \
__asm__ __volatile__ ( \
- "1:\tlwl\t%0, 3(%2)\n" \
- "2:\tlwr\t%0, (%2)\n\t" \
+ "1:\t"user_lwl("%0", "3(%2)")"\n" \
+ "2:\t"user_lwr("%0", "(%2)")"\n\t" \
"li\t%1, 0\n" \
"3:\n\t" \
".insn\n\t" \
@@ -306,8 +307,8 @@ extern void show_registers(struct pt_regs *regs);
#define LoadHWU(addr, value, res) \
__asm__ __volatile__ ( \
".set\tnoat\n" \
- "1:\tlbu\t%0, 1(%2)\n" \
- "2:\tlbu\t$1, 0(%2)\n\t" \
+ "1:\t"user_lbu("%0", "1(%2)")"\n" \
+ "2:\t"user_lbu("$1", "0(%2)")"\n\t" \
"sll\t%0, 0x8\n\t" \
"or\t%0, $1\n\t" \
"li\t%1, 0\n" \
@@ -327,8 +328,8 @@ extern void show_registers(struct pt_regs *regs);
#define LoadWU(addr, value, res) \
__asm__ __volatile__ ( \
- "1:\tlwl\t%0, 3(%2)\n" \
- "2:\tlwr\t%0, (%2)\n\t" \
+ "1:\t"user_lwl("%0", "3(%2)")"\n" \
+ "2:\t"user_lwr("%0", "(%2)")"\n\t" \
"dsll\t%0, %0, 32\n\t" \
"dsrl\t%0, %0, 32\n\t" \
"li\t%1, 0\n" \
@@ -366,9 +367,9 @@ extern void show_registers(struct pt_regs *regs);
#define StoreHW(addr, value, res) \
__asm__ __volatile__ ( \
".set\tnoat\n" \
- "1:\tsb\t%1, 0(%2)\n\t" \
+ "1:\t"user_sb("%1", "0(%2)")"\n" \
"srl\t$1,%1, 0x8\n" \
- "2:\tsb\t$1, 1(%2)\n\t" \
+ "2:\t"user_sb("$1", "1(%2)")"\n" \
".set\tat\n\t" \
"li\t%0, 0\n" \
"3:\n\t" \
@@ -386,8 +387,8 @@ extern void show_registers(struct pt_regs *regs);
#define StoreW(addr, value, res) \
__asm__ __volatile__ ( \
- "1:\tswl\t%1, 3(%2)\n" \
- "2:\tswr\t%1, (%2)\n\t" \
+ "1:\t"user_swl("%1", "3(%2)")"\n" \
+ "2:\t"user_swr("%1", "(%2)")"\n\t" \
"li\t%0, 0\n" \
"3:\n\t" \
".insn\n\t" \
@@ -430,7 +431,9 @@ static void emulate_load_store_insn(struct pt_regs *regs,
unsigned long origpc;
unsigned long orig31;
void __user *fault_addr = NULL;
-
+#ifdef CONFIG_EVA
+ mm_segment_t seg;
+#endif
origpc = (unsigned long)pc;
orig31 = regs->regs[31];
@@ -475,6 +478,88 @@ static void emulate_load_store_insn(struct pt_regs *regs,
* The remaining opcodes are the ones that are really of
* interest.
*/
+#ifdef CONFIG_EVA
+ case spec3_op:
+ /*
+ * we can land here only from kernel accessing user memory,
+ * so we need to "switch" the address limit to user space, so
+ * address check can work properly.
+ */
+ seg = get_fs();
+ set_fs(USER_DS);
+ switch (insn.spec3_format.func) {
+ case lhe_op:
+ if (!access_ok(VERIFY_READ, addr, 2)) {
+ set_fs(seg);
+ goto sigbus;
+ }
+ LoadHW(addr, value, res);
+ if (res) {
+ set_fs(seg);
+ goto fault;
+ }
+ compute_return_epc(regs);
+ regs->regs[insn.spec3_format.rt] = value;
+ break;
+ case lwe_op:
+ if (!access_ok(VERIFY_READ, addr, 4)) {
+ set_fs(seg);
+ goto sigbus;
+ }
+ LoadW(addr, value, res);
+ if (res) {
+ set_fs(seg);
+ goto fault;
+ }
+ compute_return_epc(regs);
+ regs->regs[insn.spec3_format.rt] = value;
+ break;
+ case lhue_op:
+ if (!access_ok(VERIFY_READ, addr, 2)) {
+ set_fs(seg);
+ goto sigbus;
+ }
+ LoadHWU(addr, value, res);
+ if (res) {
+ set_fs(seg);
+ goto fault;
+ }
+ compute_return_epc(regs);
+ regs->regs[insn.spec3_format.rt] = value;
+ break;
+ case she_op:
+ if (!access_ok(VERIFY_WRITE, addr, 2)) {
+ set_fs(seg);
+ goto sigbus;
+ }
+ compute_return_epc(regs);
+ value = regs->regs[insn.spec3_format.rt];
+ StoreHW(addr, value, res);
+ if (res) {
+ set_fs(seg);
+ goto fault;
+ }
+ break;
+ case swe_op:
+ if (!access_ok(VERIFY_WRITE, addr, 4)) {
+ set_fs(seg);
+ goto sigbus;
+ }
+ compute_return_epc(regs);
+ value = regs->regs[insn.spec3_format.rt];
+ StoreW(addr, value, res);
+ if (res) {
+ set_fs(seg);
+ goto fault;
+ }
+ break;
+ default:
+ set_fs(seg);
+ goto sigill;
+ }
+ set_fs(seg);
+ break;
+#endif
case lh_op:
if (!access_ok(VERIFY_READ, addr, 2))
goto sigbus;
diff --git a/arch/mips/kernel/vpe-cmp.c b/arch/mips/kernel/vpe-cmp.c
new file mode 100644
index 00000000000..9268ebc0f61
--- /dev/null
+++ b/arch/mips/kernel/vpe-cmp.c
@@ -0,0 +1,180 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include <asm/vpe.h>
+
+static int major;
+
+void cleanup_tc(struct tc *tc)
+{
+
+}
+
+static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct vpe *vpe = get_vpe(aprp_cpu_index());
+ struct vpe_notifications *notifier;
+
+ list_for_each_entry(notifier, &vpe->notify, list)
+ notifier->stop(aprp_cpu_index());
+
+ release_progmem(vpe->load_addr);
+ vpe->state = VPE_STATE_UNUSED;
+
+ return len;
+}
+static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill);
+
+static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr,
+ char *buf)
+{
+ struct vpe *vpe = get_vpe(aprp_cpu_index());
+
+ return sprintf(buf, "%d\n", vpe->ntcs);
+}
+
+static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct vpe *vpe = get_vpe(aprp_cpu_index());
+ unsigned long new;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &new);
+ if (ret < 0)
+ return ret;
+
+ /* APRP can only reserve one TC in a VPE and no more. */
+ if (new != 1)
+ return -EINVAL;
+
+ vpe->ntcs = new;
+
+ return len;
+}
+static DEVICE_ATTR_RW(ntcs);
+
+static struct attribute *vpe_attrs[] = {
+ &dev_attr_kill.attr,
+ &dev_attr_ntcs.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(vpe);
+
+static void vpe_device_release(struct device *cd)
+{
+ kfree(cd);
+}
+
+static struct class vpe_class = {
+ .name = "vpe",
+ .owner = THIS_MODULE,
+ .dev_release = vpe_device_release,
+ .dev_groups = vpe_groups,
+};
+
+static struct device vpe_device;
+
+int __init vpe_module_init(void)
+{
+ struct vpe *v = NULL;
+ struct tc *t;
+ int err;
+
+ if (!cpu_has_mipsmt) {
+ pr_warn("VPE loader: not a MIPS MT capable processor\n");
+ return -ENODEV;
+ }
+
+ if (num_possible_cpus() - aprp_cpu_index() < 1) {
+ pr_warn("No VPEs reserved for AP/SP, not initialize VPE loader\n"
+ "Pass maxcpus=<n> argument as kernel argument\n");
+ return -ENODEV;
+ }
+
+ major = register_chrdev(0, VPE_MODULE_NAME, &vpe_fops);
+ if (major < 0) {
+ pr_warn("VPE loader: unable to register character device\n");
+ return major;
+ }
+
+ err = class_register(&vpe_class);
+ if (err) {
+ pr_err("vpe_class registration failed\n");
+ goto out_chrdev;
+ }
+
+ device_initialize(&vpe_device);
+ vpe_device.class = &vpe_class,
+ vpe_device.parent = NULL,
+ dev_set_name(&vpe_device, "vpe_sp");
+ vpe_device.devt = MKDEV(major, VPE_MODULE_MINOR);
+ err = device_add(&vpe_device);
+ if (err) {
+ pr_err("Adding vpe_device failed\n");
+ goto out_class;
+ }
+
+ t = alloc_tc(aprp_cpu_index());
+ if (!t) {
+ pr_warn("VPE: unable to allocate TC\n");
+ err = -ENOMEM;
+ goto out_dev;
+ }
+
+ /* VPE */
+ v = alloc_vpe(aprp_cpu_index());
+ if (v == NULL) {
+ pr_warn("VPE: unable to allocate VPE\n");
+ kfree(t);
+ err = -ENOMEM;
+ goto out_dev;
+ }
+
+ v->ntcs = 1;
+
+ /* add the tc to the list of this vpe's tc's. */
+ list_add(&t->tc, &v->tc);
+
+ /* TC */
+ t->pvpe = v; /* set the parent vpe */
+
+ return 0;
+
+out_dev:
+ device_del(&vpe_device);
+
+out_class:
+ class_unregister(&vpe_class);
+
+out_chrdev:
+ unregister_chrdev(major, VPE_MODULE_NAME);
+
+ return err;
+}
+
+void __exit vpe_module_exit(void)
+{
+ struct vpe *v, *n;
+
+ device_del(&vpe_device);
+ class_unregister(&vpe_class);
+ unregister_chrdev(major, VPE_MODULE_NAME);
+
+ /* No locking needed here */
+ list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list)
+ if (v->state != VPE_STATE_UNUSED)
+ release_vpe(v);
+}
diff --git a/arch/mips/kernel/vpe-mt.c b/arch/mips/kernel/vpe-mt.c
new file mode 100644
index 00000000000..2e003b11a09
--- /dev/null
+++ b/arch/mips/kernel/vpe-mt.c
@@ -0,0 +1,521 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#include <asm/mips_mt.h>
+#include <asm/vpe.h>
+
+static int major;
+
+/* The number of TCs and VPEs physically available on the core */
+static int hw_tcs, hw_vpes;
+
+/* We are prepared so configure and start the VPE... */
+int vpe_run(struct vpe *v)
+{
+ unsigned long flags, val, dmt_flag;
+ struct vpe_notifications *notifier;
+ unsigned int vpeflags;
+ struct tc *t;
+
+ /* check we are the Master VPE */
+ local_irq_save(flags);
+ val = read_c0_vpeconf0();
+ if (!(val & VPECONF0_MVP)) {
+ pr_warn("VPE loader: only Master VPE's are able to config MT\n");
+ local_irq_restore(flags);
+
+ return -1;
+ }
+
+ dmt_flag = dmt();
+ vpeflags = dvpe();
+
+ if (list_empty(&v->tc)) {
+ evpe(vpeflags);
+ emt(dmt_flag);
+ local_irq_restore(flags);
+
+ pr_warn("VPE loader: No TC's associated with VPE %d\n",
+ v->minor);
+
+ return -ENOEXEC;
+ }
+
+ t = list_first_entry(&v->tc, struct tc, tc);
+
+ /* Put MVPE's into 'configuration state' */
+ set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ settc(t->index);
+
+ /* should check it is halted, and not activated */
+ if ((read_tc_c0_tcstatus() & TCSTATUS_A) ||
+ !(read_tc_c0_tchalt() & TCHALT_H)) {
+ evpe(vpeflags);
+ emt(dmt_flag);
+ local_irq_restore(flags);
+
+ pr_warn("VPE loader: TC %d is already active!\n",
+ t->index);
+
+ return -ENOEXEC;
+ }
+
+ /*
+ * Write the address we want it to start running from in the TCPC
+ * register.
+ */
+ write_tc_c0_tcrestart((unsigned long)v->__start);
+ write_tc_c0_tccontext((unsigned long)0);
+
+ /*
+ * Mark the TC as activated, not interrupt exempt and not dynamically
+ * allocatable
+ */
+ val = read_tc_c0_tcstatus();
+ val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;
+ write_tc_c0_tcstatus(val);
+
+ write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
+
+ /*
+ * The sde-kit passes 'memsize' to __start in $a3, so set something
+ * here... Or set $a3 to zero and define DFLT_STACK_SIZE and
+ * DFLT_HEAP_SIZE when you compile your program
+ */
+ mttgpr(6, v->ntcs);
+ mttgpr(7, physical_memsize);
+
+ /* set up VPE1 */
+ /*
+ * bind the TC to VPE 1 as late as possible so we only have the final
+ * VPE registers to set up, and so an EJTAG probe can trigger on it
+ */
+ write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1);
+
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA));
+
+ back_to_back_c0_hazard();
+
+ /* Set up the XTC bit in vpeconf0 to point at our tc */
+ write_vpe_c0_vpeconf0((read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
+ | (t->index << VPECONF0_XTC_SHIFT));
+
+ back_to_back_c0_hazard();
+
+ /* enable this VPE */
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+
+ /* clear out any left overs from a previous program */
+ write_vpe_c0_status(0);
+ write_vpe_c0_cause(0);
+
+ /* take system out of configuration state */
+ clear_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ /*
+ * SMVP kernels manage VPE enable independently, but uniprocessor
+ * kernels need to turn it on, even if that wasn't the pre-dvpe() state.
+ */
+#ifdef CONFIG_SMP
+ evpe(vpeflags);
+#else
+ evpe(EVPE_ENABLE);
+#endif
+ emt(dmt_flag);
+ local_irq_restore(flags);
+
+ list_for_each_entry(notifier, &v->notify, list)
+ notifier->start(VPE_MODULE_MINOR);
+
+ return 0;
+}
+
+void cleanup_tc(struct tc *tc)
+{
+ unsigned long flags;
+ unsigned int mtflags, vpflags;
+ int tmp;
+
+ local_irq_save(flags);
+ mtflags = dmt();
+ vpflags = dvpe();
+ /* Put MVPE's into 'configuration state' */
+ set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ settc(tc->index);
+ tmp = read_tc_c0_tcstatus();
+
+ /* mark not allocated and not dynamically allocatable */
+ tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+ tmp |= TCSTATUS_IXMT; /* interrupt exempt */
+ write_tc_c0_tcstatus(tmp);
+
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+
+ clear_c0_mvpcontrol(MVPCONTROL_VPC);
+ evpe(vpflags);
+ emt(mtflags);
+ local_irq_restore(flags);
+}
+
+/* module wrapper entry points */
+/* give me a vpe */
+void *vpe_alloc(void)
+{
+ int i;
+ struct vpe *v;
+
+ /* find a vpe */
+ for (i = 1; i < MAX_VPES; i++) {
+ v = get_vpe(i);
+ if (v != NULL) {
+ v->state = VPE_STATE_INUSE;
+ return v;
+ }
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(vpe_alloc);
+
+/* start running from here */
+int vpe_start(void *vpe, unsigned long start)
+{
+ struct vpe *v = vpe;
+
+ v->__start = start;
+ return vpe_run(v);
+}
+EXPORT_SYMBOL(vpe_start);
+
+/* halt it for now */
+int vpe_stop(void *vpe)
+{
+ struct vpe *v = vpe;
+ struct tc *t;
+ unsigned int evpe_flags;
+
+ evpe_flags = dvpe();
+
+ t = list_entry(v->tc.next, struct tc, tc);
+ if (t != NULL) {
+ settc(t->index);
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA);
+ }
+
+ evpe(evpe_flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(vpe_stop);
+
+/* I've done with it thank you */
+int vpe_free(void *vpe)
+{
+ struct vpe *v = vpe;
+ struct tc *t;
+ unsigned int evpe_flags;
+
+ t = list_entry(v->tc.next, struct tc, tc);
+ if (t == NULL)
+ return -ENOEXEC;
+
+ evpe_flags = dvpe();
+
+ /* Put MVPE's into 'configuration state' */
+ set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ settc(t->index);
+ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA);
+
+ /* halt the TC */
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+
+ /* mark the TC unallocated */
+ write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A);
+
+ v->state = VPE_STATE_UNUSED;
+
+ clear_c0_mvpcontrol(MVPCONTROL_VPC);
+ evpe(evpe_flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(vpe_free);
+
+static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct vpe *vpe = get_vpe(aprp_cpu_index());
+ struct vpe_notifications *notifier;
+
+ list_for_each_entry(notifier, &vpe->notify, list)
+ notifier->stop(aprp_cpu_index());
+
+ release_progmem(vpe->load_addr);
+ cleanup_tc(get_tc(aprp_cpu_index()));
+ vpe_stop(vpe);
+ vpe_free(vpe);
+
+ return len;
+}
+static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill);
+
+static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr,
+ char *buf)
+{
+ struct vpe *vpe = get_vpe(aprp_cpu_index());
+
+ return sprintf(buf, "%d\n", vpe->ntcs);
+}
+
+static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct vpe *vpe = get_vpe(aprp_cpu_index());
+ unsigned long new;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &new);
+ if (ret < 0)
+ return ret;
+
+ if (new == 0 || new > (hw_tcs - aprp_cpu_index()))
+ return -EINVAL;
+
+ vpe->ntcs = new;
+
+ return len;
+}
+static DEVICE_ATTR_RW(ntcs);
+
+static struct attribute *vpe_attrs[] = {
+ &dev_attr_kill.attr,
+ &dev_attr_ntcs.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(vpe);
+
+static void vpe_device_release(struct device *cd)
+{
+ kfree(cd);
+}
+
+static struct class vpe_class = {
+ .name = "vpe",
+ .owner = THIS_MODULE,
+ .dev_release = vpe_device_release,
+ .dev_groups = vpe_groups,
+};
+
+static struct device vpe_device;
+
+int __init vpe_module_init(void)
+{
+ unsigned int mtflags, vpflags;
+ unsigned long flags, val;
+ struct vpe *v = NULL;
+ struct tc *t;
+ int tc, err;
+
+ if (!cpu_has_mipsmt) {
+ pr_warn("VPE loader: not a MIPS MT capable processor\n");
+ return -ENODEV;
+ }
+
+ if (vpelimit == 0) {
+ pr_warn("No VPEs reserved for AP/SP, not initialize VPE loader\n"
+ "Pass maxvpes=<n> argument as kernel argument\n");
+
+ return -ENODEV;
+ }
+
+ if (aprp_cpu_index() == 0) {
+ pr_warn("No TCs reserved for AP/SP, not initialize VPE loader\n"
+ "Pass maxtcs=<n> argument as kernel argument\n");
+
+ return -ENODEV;
+ }
+
+ major = register_chrdev(0, VPE_MODULE_NAME, &vpe_fops);
+ if (major < 0) {
+ pr_warn("VPE loader: unable to register character device\n");
+ return major;
+ }
+
+ err = class_register(&vpe_class);
+ if (err) {
+ pr_err("vpe_class registration failed\n");
+ goto out_chrdev;
+ }
+
+ device_initialize(&vpe_device);
+ vpe_device.class = &vpe_class,
+ vpe_device.parent = NULL,
+ dev_set_name(&vpe_device, "vpe1");
+ vpe_device.devt = MKDEV(major, VPE_MODULE_MINOR);
+ err = device_add(&vpe_device);
+ if (err) {
+ pr_err("Adding vpe_device failed\n");
+ goto out_class;
+ }
+
+ local_irq_save(flags);
+ mtflags = dmt();
+ vpflags = dvpe();
+
+ /* Put MVPE's into 'configuration state' */
+ set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ val = read_c0_mvpconf0();
+ hw_tcs = (val & MVPCONF0_PTC) + 1;
+ hw_vpes = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+
+ for (tc = aprp_cpu_index(); tc < hw_tcs; tc++) {
+ /*
+ * Must re-enable multithreading temporarily or in case we
+ * reschedule send IPIs or similar we might hang.
+ */
+ clear_c0_mvpcontrol(MVPCONTROL_VPC);
+ evpe(vpflags);
+ emt(mtflags);
+ local_irq_restore(flags);
+ t = alloc_tc(tc);
+ if (!t) {
+ err = -ENOMEM;
+ goto out_dev;
+ }
+
+ local_irq_save(flags);
+ mtflags = dmt();
+ vpflags = dvpe();
+ set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ /* VPE's */
+ if (tc < hw_tcs) {
+ settc(tc);
+
+ v = alloc_vpe(tc);
+ if (v == NULL) {
+ pr_warn("VPE: unable to allocate VPE\n");
+ goto out_reenable;
+ }
+
+ v->ntcs = hw_tcs - aprp_cpu_index();
+
+ /* add the tc to the list of this vpe's tc's. */
+ list_add(&t->tc, &v->tc);
+
+ /* deactivate all but vpe0 */
+ if (tc >= aprp_cpu_index()) {
+ unsigned long tmp = read_vpe_c0_vpeconf0();
+
+ tmp &= ~VPECONF0_VPA;
+
+ /* master VPE */
+ tmp |= VPECONF0_MVP;
+ write_vpe_c0_vpeconf0(tmp);
+ }
+
+ /* disable multi-threading with TC's */
+ write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() &
+ ~VPECONTROL_TE);
+
+ if (tc >= vpelimit) {
+ /*
+ * Set config to be the same as vpe0,
+ * particularly kseg0 coherency alg
+ */
+ write_vpe_c0_config(read_c0_config());
+ }
+ }
+
+ /* TC's */
+ t->pvpe = v; /* set the parent vpe */
+
+ if (tc >= aprp_cpu_index()) {
+ unsigned long tmp;
+
+ settc(tc);
+
+ /*
+ * A TC that is bound to any other VPE gets bound to
+ * VPE0, ideally I'd like to make it homeless but it
+ * doesn't appear to let me bind a TC to a non-existent
+ * VPE. Which is perfectly reasonable.
+ *
+ * The (un)bound state is visible to an EJTAG probe so
+ * may notify GDB...
+ */
+ tmp = read_tc_c0_tcbind();
+ if (tmp & TCBIND_CURVPE) {
+ /* tc is bound >vpe0 */
+ write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE);
+
+ t->pvpe = get_vpe(0); /* set the parent vpe */
+ }
+
+ /* halt the TC */
+ write_tc_c0_tchalt(TCHALT_H);
+ mips_ihb();
+
+ tmp = read_tc_c0_tcstatus();
+
+ /* mark not activated and not dynamically allocatable */
+ tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+ tmp |= TCSTATUS_IXMT; /* interrupt exempt */
+ write_tc_c0_tcstatus(tmp);
+ }
+ }
+
+out_reenable:
+ /* release config state */
+ clear_c0_mvpcontrol(MVPCONTROL_VPC);
+
+ evpe(vpflags);
+ emt(mtflags);
+ local_irq_restore(flags);
+
+ return 0;
+
+out_dev:
+ device_del(&vpe_device);
+
+out_class:
+ class_unregister(&vpe_class);
+
+out_chrdev:
+ unregister_chrdev(major, VPE_MODULE_NAME);
+
+ return err;
+}
+
+void __exit vpe_module_exit(void)
+{
+ struct vpe *v, *n;
+
+ device_del(&vpe_device);
+ class_unregister(&vpe_class);
+ unregister_chrdev(major, VPE_MODULE_NAME);
+
+ /* No locking needed here */
+ list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) {
+ if (v->state != VPE_STATE_UNUSED)
+ release_vpe(v);
+ }
+}
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 59b2b3cd788..11da314565c 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1,37 +1,22 @@
/*
- * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-
-/*
- * VPE support module
- *
- * Provides support for loading a MIPS SP program on VPE1.
- * The SP environment is rather simple, no tlb's. It needs to be relocatable
- * (or partially linked). You should initialise your stack in the startup
- * code. This loader looks for the symbol __start and sets up
- * execution to resume from there. The MIPS SDE kit contains suitable examples.
+ * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*
- * To load and run, simply cat a SP 'program file' to /dev/vpe1.
- * i.e cat spapp >/dev/vpe1.
+ * VPE spport module for loading a MIPS SP program into VPE1. The SP
+ * environment is rather simple since there are no TLBs. It needs
+ * to be relocatable (or partiall linked). Initialize your stack in
+ * the startup-code. The loader looks for the symbol __start and sets
+ * up the execution to resume from there. To load and run, simply do
+ * a cat SP 'binary' to the /dev/vpe1 device.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/vmalloc.h>
@@ -46,13 +31,10 @@
#include <asm/mipsmtregs.h>
#include <asm/cacheflush.h>
#include <linux/atomic.h>
-#include <asm/cpu.h>
#include <asm/mips_mt.h>
#include <asm/processor.h>
#include <asm/vpe.h>
-typedef void *vpe_handle;
-
#ifndef ARCH_SHF_SMALL
#define ARCH_SHF_SMALL 0
#endif
@@ -60,96 +42,15 @@ typedef void *vpe_handle;
/* If this is set, the section belongs in the init part of the module */
#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
-/*
- * The number of TCs and VPEs physically available on the core
- */
-static int hw_tcs, hw_vpes;
-static char module_name[] = "vpe";
-static int major;
-static const int minor = 1; /* fixed for now */
-
-/* grab the likely amount of memory we will need. */
-#ifdef CONFIG_MIPS_VPE_LOADER_TOM
-#define P_SIZE (2 * 1024 * 1024)
-#else
-/* add an overhead to the max kmalloc size for non-striped symbols/etc */
-#define P_SIZE (256 * 1024)
-#endif
-
-extern unsigned long physical_memsize;
-
-#define MAX_VPES 16
-#define VPE_PATH_MAX 256
-
-enum vpe_state {
- VPE_STATE_UNUSED = 0,
- VPE_STATE_INUSE,
- VPE_STATE_RUNNING
-};
-
-enum tc_state {
- TC_STATE_UNUSED = 0,
- TC_STATE_INUSE,
- TC_STATE_RUNNING,
- TC_STATE_DYNAMIC
-};
-
-struct vpe {
- enum vpe_state state;
-
- /* (device) minor associated with this vpe */
- int minor;
-
- /* elfloader stuff */
- void *load_addr;
- unsigned long len;
- char *pbuffer;
- unsigned long plen;
- unsigned int uid, gid;
- char cwd[VPE_PATH_MAX];
-
- unsigned long __start;
-
- /* tc's associated with this vpe */
- struct list_head tc;
-
- /* The list of vpe's */
- struct list_head list;
-
- /* shared symbol address */
- void *shared_ptr;
-
- /* the list of who wants to know when something major happens */
- struct list_head notify;
-
- unsigned int ntcs;
-};
-
-struct tc {
- enum tc_state state;
- int index;
-
- struct vpe *pvpe; /* parent VPE */
- struct list_head tc; /* The list of TC's with this VPE */
- struct list_head list; /* The global list of tc's */
-};
-
-struct {
- spinlock_t vpe_list_lock;
- struct list_head vpe_list; /* Virtual processing elements */
- spinlock_t tc_list_lock;
- struct list_head tc_list; /* Thread contexts */
-} vpecontrol = {
+struct vpe_control vpecontrol = {
.vpe_list_lock = __SPIN_LOCK_UNLOCKED(vpe_list_lock),
.vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list),
.tc_list_lock = __SPIN_LOCK_UNLOCKED(tc_list_lock),
.tc_list = LIST_HEAD_INIT(vpecontrol.tc_list)
};
-static void release_progmem(void *ptr);
-
/* get the vpe associated with this minor */
-static struct vpe *get_vpe(int minor)
+struct vpe *get_vpe(int minor)
{
struct vpe *res, *v;
@@ -159,7 +60,7 @@ static struct vpe *get_vpe(int minor)
res = NULL;
spin_lock(&vpecontrol.vpe_list_lock);
list_for_each_entry(v, &vpecontrol.vpe_list, list) {
- if (v->minor == minor) {
+ if (v->minor == VPE_MODULE_MINOR) {
res = v;
break;
}
@@ -170,7 +71,7 @@ static struct vpe *get_vpe(int minor)
}
/* get the vpe associated with this minor */
-static struct tc *get_tc(int index)
+struct tc *get_tc(int index)
{
struct tc *res, *t;
@@ -188,12 +89,13 @@ static struct tc *get_tc(int index)
}
/* allocate a vpe and associate it with this minor (or index) */
-static struct vpe *alloc_vpe(int minor)
+struct vpe *alloc_vpe(int minor)
{
struct vpe *v;
- if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL)
- return NULL;
+ v = kzalloc(sizeof(struct vpe), GFP_KERNEL);
+ if (v == NULL)
+ goto out;
INIT_LIST_HEAD(&v->tc);
spin_lock(&vpecontrol.vpe_list_lock);
@@ -201,17 +103,19 @@ static struct vpe *alloc_vpe(int minor)
spin_unlock(&vpecontrol.vpe_list_lock);
INIT_LIST_HEAD(&v->notify);
- v->minor = minor;
+ v->minor = VPE_MODULE_MINOR;
+out:
return v;
}
/* allocate a tc. At startup only tc0 is running, all other can be halted. */
-static struct tc *alloc_tc(int index)
+struct tc *alloc_tc(int index)
{
struct tc *tc;
- if ((tc = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL)
+ tc = kzalloc(sizeof(struct tc), GFP_KERNEL);
+ if (tc == NULL)
goto out;
INIT_LIST_HEAD(&tc->tc);
@@ -226,7 +130,7 @@ out:
}
/* clean up and free everything */
-static void release_vpe(struct vpe *v)
+void release_vpe(struct vpe *v)
{
list_del(&v->list);
if (v->load_addr)
@@ -234,28 +138,8 @@ static void release_vpe(struct vpe *v)
kfree(v);
}
-static void __maybe_unused dump_mtregs(void)
-{
- unsigned long val;
-
- val = read_c0_config3();
- printk("config3 0x%lx MT %ld\n", val,
- (val & CONFIG3_MT) >> CONFIG3_MT_SHIFT);
-
- val = read_c0_mvpcontrol();
- printk("MVPControl 0x%lx, STLB %ld VPC %ld EVP %ld\n", val,
- (val & MVPCONTROL_STLB) >> MVPCONTROL_STLB_SHIFT,
- (val & MVPCONTROL_VPC) >> MVPCONTROL_VPC_SHIFT,
- (val & MVPCONTROL_EVP));
-
- val = read_c0_mvpconf0();
- printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
- (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
- val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
-}
-
-/* Find some VPE program space */
-static void *alloc_progmem(unsigned long len)
+/* Find some VPE program space */
+void *alloc_progmem(unsigned long len)
{
void *addr;
@@ -274,7 +158,7 @@ static void *alloc_progmem(unsigned long len)
return addr;
}
-static void release_progmem(void *ptr)
+void release_progmem(void *ptr)
{
#ifndef CONFIG_MIPS_VPE_LOADER_TOM
kfree(ptr);
@@ -282,7 +166,7 @@ static void release_progmem(void *ptr)
}
/* Update size with this section: return offset. */
-static long get_offset(unsigned long *size, Elf_Shdr * sechdr)
+static long get_offset(unsigned long *size, Elf_Shdr *sechdr)
{
long ret;
@@ -295,8 +179,8 @@ static long get_offset(unsigned long *size, Elf_Shdr * sechdr)
might -- code, read-only data, read-write data, small data. Tally
sizes, and place the offsets into sh_entsize fields: high bit means it
belongs in init. */
-static void layout_sections(struct module *mod, const Elf_Ehdr * hdr,
- Elf_Shdr * sechdrs, const char *secstrings)
+static void layout_sections(struct module *mod, const Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs, const char *secstrings)
{
static unsigned long const masks[][2] = {
/* NOTE: all executable code must be the first section
@@ -316,7 +200,6 @@ static void layout_sections(struct module *mod, const Elf_Ehdr * hdr,
for (i = 0; i < hdr->e_shnum; ++i) {
Elf_Shdr *s = &sechdrs[i];
- // || strncmp(secstrings + s->sh_name, ".init", 5) == 0)
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|| (s->sh_flags & masks[m][1])
|| s->sh_entsize != ~0UL)
@@ -331,7 +214,6 @@ static void layout_sections(struct module *mod, const Elf_Ehdr * hdr,
}
}
-
/* from module-elf32.c, but subverted a little */
struct mips_hi16 {
@@ -354,20 +236,18 @@ static int apply_r_mips_gprel16(struct module *me, uint32_t *location,
{
int rel;
- if( !(*location & 0xffff) ) {
+ if (!(*location & 0xffff)) {
rel = (int)v - gp_addr;
- }
- else {
+ } else {
/* .sbss + gp(relative) + offset */
/* kludge! */
rel = (int)(short)((int)v + gp_offs +
(int)(short)(*location & 0xffff) - gp_addr);
}
- if( (rel > 32768) || (rel < -32768) ) {
- printk(KERN_DEBUG "VPE loader: apply_r_mips_gprel16: "
- "relative address 0x%x out of range of gp register\n",
- rel);
+ if ((rel > 32768) || (rel < -32768)) {
+ pr_debug("VPE loader: apply_r_mips_gprel16: relative address 0x%x out of range of gp register\n",
+ rel);
return -ENOEXEC;
}
@@ -381,12 +261,12 @@ static int apply_r_mips_pc16(struct module *me, uint32_t *location,
{
int rel;
rel = (((unsigned int)v - (unsigned int)location));
- rel >>= 2; // because the offset is in _instructions_ not bytes.
- rel -= 1; // and one instruction less due to the branch delay slot.
+ rel >>= 2; /* because the offset is in _instructions_ not bytes. */
+ rel -= 1; /* and one instruction less due to the branch delay slot. */
- if( (rel > 32768) || (rel < -32768) ) {
- printk(KERN_DEBUG "VPE loader: "
- "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
+ if ((rel > 32768) || (rel < -32768)) {
+ pr_debug("VPE loader: apply_r_mips_pc16: relative address out of range 0x%x\n",
+ rel);
return -ENOEXEC;
}
@@ -407,8 +287,7 @@ static int apply_r_mips_26(struct module *me, uint32_t *location,
Elf32_Addr v)
{
if (v % 4) {
- printk(KERN_DEBUG "VPE loader: apply_r_mips_26 "
- " unaligned relocation\n");
+ pr_debug("VPE loader: apply_r_mips_26: unaligned relocation\n");
return -ENOEXEC;
}
@@ -439,7 +318,7 @@ static int apply_r_mips_hi16(struct module *me, uint32_t *location,
* the carry we need to add. Save the information, and let LO16 do the
* actual relocation.
*/
- n = kmalloc(sizeof *n, GFP_KERNEL);
+ n = kmalloc(sizeof(*n), GFP_KERNEL);
if (!n)
return -ENOMEM;
@@ -471,9 +350,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
* The value for the HI16 had best be the same.
*/
if (v != l->value) {
- printk(KERN_DEBUG "VPE loader: "
- "apply_r_mips_lo16/hi16: \t"
- "inconsistent value information\n");
+ pr_debug("VPE loader: apply_r_mips_lo16/hi16: inconsistent value information\n");
goto out_free;
}
@@ -569,20 +446,19 @@ static int apply_relocations(Elf32_Shdr *sechdrs,
+ ELF32_R_SYM(r_info);
if (!sym->st_value) {
- printk(KERN_DEBUG "%s: undefined weak symbol %s\n",
- me->name, strtab + sym->st_name);
+ pr_debug("%s: undefined weak symbol %s\n",
+ me->name, strtab + sym->st_name);
/* just print the warning, dont barf */
}
v = sym->st_value;
res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
- if( res ) {
+ if (res) {
char *r = rstrs[ELF32_R_TYPE(r_info)];
- printk(KERN_WARNING "VPE loader: .text+0x%x "
- "relocation type %s for symbol \"%s\" failed\n",
- rel[i].r_offset, r ? r : "UNKNOWN",
- strtab + sym->st_name);
+ pr_warn("VPE loader: .text+0x%x relocation type %s for symbol \"%s\" failed\n",
+ rel[i].r_offset, r ? r : "UNKNOWN",
+ strtab + sym->st_name);
return res;
}
}
@@ -597,10 +473,8 @@ static inline void save_gp_address(unsigned int secbase, unsigned int rel)
}
/* end module-elf32.c */
-
-
/* Change all symbols so that sh_value encodes the pointer directly. */
-static void simplify_symbols(Elf_Shdr * sechdrs,
+static void simplify_symbols(Elf_Shdr *sechdrs,
unsigned int symindex,
const char *strtab,
const char *secstrings,
@@ -641,18 +515,16 @@ static void simplify_symbols(Elf_Shdr * sechdrs,
break;
case SHN_MIPS_SCOMMON:
- printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON "
- "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name,
- sym[i].st_shndx);
- // .sbss section
+ pr_debug("simplify_symbols: ignoring SHN_MIPS_SCOMMON symbol <%s> st_shndx %d\n",
+ strtab + sym[i].st_name, sym[i].st_shndx);
+ /* .sbss section */
break;
default:
secbase = sechdrs[sym[i].st_shndx].sh_addr;
- if (strncmp(strtab + sym[i].st_name, "_gp", 3) == 0) {
+ if (strncmp(strtab + sym[i].st_name, "_gp", 3) == 0)
save_gp_address(secbase, sym[i].st_value);
- }
sym[i].st_value += secbase;
break;
@@ -661,142 +533,21 @@ static void simplify_symbols(Elf_Shdr * sechdrs,
}
#ifdef DEBUG_ELFLOADER
-static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex,
+static void dump_elfsymbols(Elf_Shdr *sechdrs, unsigned int symindex,
const char *strtab, struct module *mod)
{
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
- printk(KERN_DEBUG "dump_elfsymbols: n %d\n", n);
+ pr_debug("dump_elfsymbols: n %d\n", n);
for (i = 1; i < n; i++) {
- printk(KERN_DEBUG " i %d name <%s> 0x%x\n", i,
- strtab + sym[i].st_name, sym[i].st_value);
+ pr_debug(" i %d name <%s> 0x%x\n", i, strtab + sym[i].st_name,
+ sym[i].st_value);
}
}
#endif
-/* We are prepared so configure and start the VPE... */
-static int vpe_run(struct vpe * v)
-{
- unsigned long flags, val, dmt_flag;
- struct vpe_notifications *n;
- unsigned int vpeflags;
- struct tc *t;
-
- /* check we are the Master VPE */
- local_irq_save(flags);
- val = read_c0_vpeconf0();
- if (!(val & VPECONF0_MVP)) {
- printk(KERN_WARNING
- "VPE loader: only Master VPE's are allowed to configure MT\n");
- local_irq_restore(flags);
-
- return -1;
- }
-
- dmt_flag = dmt();
- vpeflags = dvpe();
-
- if (list_empty(&v->tc)) {
- evpe(vpeflags);
- emt(dmt_flag);
- local_irq_restore(flags);
-
- printk(KERN_WARNING
- "VPE loader: No TC's associated with VPE %d\n",
- v->minor);
-
- return -ENOEXEC;
- }
-
- t = list_first_entry(&v->tc, struct tc, tc);
-
- /* Put MVPE's into 'configuration state' */
- set_c0_mvpcontrol(MVPCONTROL_VPC);
-
- settc(t->index);
-
- /* should check it is halted, and not activated */
- if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) {
- evpe(vpeflags);
- emt(dmt_flag);
- local_irq_restore(flags);
-
- printk(KERN_WARNING "VPE loader: TC %d is already active!\n",
- t->index);
-
- return -ENOEXEC;
- }
-
- /* Write the address we want it to start running from in the TCPC register. */
- write_tc_c0_tcrestart((unsigned long)v->__start);
- write_tc_c0_tccontext((unsigned long)0);
-
- /*
- * Mark the TC as activated, not interrupt exempt and not dynamically
- * allocatable
- */
- val = read_tc_c0_tcstatus();
- val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;
- write_tc_c0_tcstatus(val);
-
- write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
-
- /*
- * The sde-kit passes 'memsize' to __start in $a3, so set something
- * here... Or set $a3 to zero and define DFLT_STACK_SIZE and
- * DFLT_HEAP_SIZE when you compile your program
- */
- mttgpr(6, v->ntcs);
- mttgpr(7, physical_memsize);
-
- /* set up VPE1 */
- /*
- * bind the TC to VPE 1 as late as possible so we only have the final
- * VPE registers to set up, and so an EJTAG probe can trigger on it
- */
- write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1);
-
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA));
-
- back_to_back_c0_hazard();
-
- /* Set up the XTC bit in vpeconf0 to point at our tc */
- write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
- | (t->index << VPECONF0_XTC_SHIFT));
-
- back_to_back_c0_hazard();
-
- /* enable this VPE */
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
-
- /* clear out any left overs from a previous program */
- write_vpe_c0_status(0);
- write_vpe_c0_cause(0);
-
- /* take system out of configuration state */
- clear_c0_mvpcontrol(MVPCONTROL_VPC);
-
- /*
- * SMTC/SMVP kernels manage VPE enable independently,
- * but uniprocessor kernels need to turn it on, even
- * if that wasn't the pre-dvpe() state.
- */
-#ifdef CONFIG_SMP
- evpe(vpeflags);
-#else
- evpe(EVPE_ENABLE);
-#endif
- emt(dmt_flag);
- local_irq_restore(flags);
-
- list_for_each_entry(n, &v->notify, list)
- n->start(minor);
-
- return 0;
-}
-
-static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
+static int find_vpe_symbols(struct vpe *v, Elf_Shdr *sechdrs,
unsigned int symindex, const char *strtab,
struct module *mod)
{
@@ -804,16 +555,14 @@ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
for (i = 1; i < n; i++) {
- if (strcmp(strtab + sym[i].st_name, "__start") == 0) {
+ if (strcmp(strtab + sym[i].st_name, "__start") == 0)
v->__start = sym[i].st_value;
- }
- if (strcmp(strtab + sym[i].st_name, "vpe_shared") == 0) {
+ if (strcmp(strtab + sym[i].st_name, "vpe_shared") == 0)
v->shared_ptr = (void *)sym[i].st_value;
- }
}
- if ( (v->__start == 0) || (v->shared_ptr == NULL))
+ if ((v->__start == 0) || (v->shared_ptr == NULL))
return -1;
return 0;
@@ -824,14 +573,14 @@ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
* contents of the program (p)buffer performing relocatations/etc, free's it
* when finished.
*/
-static int vpe_elfload(struct vpe * v)
+static int vpe_elfload(struct vpe *v)
{
Elf_Ehdr *hdr;
Elf_Shdr *sechdrs;
long err = 0;
char *secstrings, *strtab = NULL;
unsigned int len, i, symindex = 0, strindex = 0, relocate = 0;
- struct module mod; // so we can re-use the relocations code
+ struct module mod; /* so we can re-use the relocations code */
memset(&mod, 0, sizeof(struct module));
strcpy(mod.name, "VPE loader");
@@ -845,8 +594,7 @@ static int vpe_elfload(struct vpe * v)
|| (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC)
|| !elf_check_arch(hdr)
|| hdr->e_shentsize != sizeof(*sechdrs)) {
- printk(KERN_WARNING
- "VPE loader: program wrong arch or weird elf version\n");
+ pr_warn("VPE loader: program wrong arch or weird elf version\n");
return -ENOEXEC;
}
@@ -855,8 +603,7 @@ static int vpe_elfload(struct vpe * v)
relocate = 1;
if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
- printk(KERN_ERR "VPE loader: program length %u truncated\n",
- len);
+ pr_err("VPE loader: program length %u truncated\n", len);
return -ENOEXEC;
}
@@ -871,22 +618,24 @@ static int vpe_elfload(struct vpe * v)
if (relocate) {
for (i = 1; i < hdr->e_shnum; i++) {
- if (sechdrs[i].sh_type != SHT_NOBITS
- && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
- printk(KERN_ERR "VPE program length %u truncated\n",
+ if ((sechdrs[i].sh_type != SHT_NOBITS) &&
+ (len < sechdrs[i].sh_offset + sechdrs[i].sh_size)) {
+ pr_err("VPE program length %u truncated\n",
len);
return -ENOEXEC;
}
/* Mark all sections sh_addr with their address in the
temporary image. */
- sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+ sechdrs[i].sh_addr = (size_t) hdr +
+ sechdrs[i].sh_offset;
/* Internal symbols and strings. */
if (sechdrs[i].sh_type == SHT_SYMTAB) {
symindex = i;
strindex = sechdrs[i].sh_link;
- strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+ strtab = (char *)hdr +
+ sechdrs[strindex].sh_offset;
}
}
layout_sections(&mod, hdr, sechdrs, secstrings);
@@ -913,8 +662,9 @@ static int vpe_elfload(struct vpe * v)
/* Update sh_addr to point to copy in image. */
sechdrs[i].sh_addr = (unsigned long)dest;
- printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",
- secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr);
+ pr_debug(" section sh_name %s sh_addr 0x%x\n",
+ secstrings + sechdrs[i].sh_name,
+ sechdrs[i].sh_addr);
}
/* Fix up syms, so that st_value is a pointer to location. */
@@ -935,17 +685,18 @@ static int vpe_elfload(struct vpe * v)
continue;
if (sechdrs[i].sh_type == SHT_REL)
- err = apply_relocations(sechdrs, strtab, symindex, i,
- &mod);
+ err = apply_relocations(sechdrs, strtab,
+ symindex, i, &mod);
else if (sechdrs[i].sh_type == SHT_RELA)
- err = apply_relocate_add(sechdrs, strtab, symindex, i,
- &mod);
+ err = apply_relocate_add(sechdrs, strtab,
+ symindex, i, &mod);
if (err < 0)
return err;
}
} else {
- struct elf_phdr *phdr = (struct elf_phdr *) ((char *)hdr + hdr->e_phoff);
+ struct elf_phdr *phdr = (struct elf_phdr *)
+ ((char *)hdr + hdr->e_phoff);
for (i = 0; i < hdr->e_phnum; i++) {
if (phdr->p_type == PT_LOAD) {
@@ -963,11 +714,15 @@ static int vpe_elfload(struct vpe * v)
if (sechdrs[i].sh_type == SHT_SYMTAB) {
symindex = i;
strindex = sechdrs[i].sh_link;
- strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+ strtab = (char *)hdr +
+ sechdrs[strindex].sh_offset;
- /* mark the symtab's address for when we try to find the
- magic symbols */
- sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+ /*
+ * mark symtab's address for when we try
+ * to find the magic symbols
+ */
+ sechdrs[i].sh_addr = (size_t) hdr +
+ sechdrs[i].sh_offset;
}
}
}
@@ -978,53 +733,19 @@ static int vpe_elfload(struct vpe * v)
if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
if (v->__start == 0) {
- printk(KERN_WARNING "VPE loader: program does not contain "
- "a __start symbol\n");
+ pr_warn("VPE loader: program does not contain a __start symbol\n");
return -ENOEXEC;
}
if (v->shared_ptr == NULL)
- printk(KERN_WARNING "VPE loader: "
- "program does not contain vpe_shared symbol.\n"
- " Unable to use AMVP (AP/SP) facilities.\n");
+ pr_warn("VPE loader: program does not contain vpe_shared symbol.\n"
+ " Unable to use AMVP (AP/SP) facilities.\n");
}
- printk(" elf loaded\n");
+ pr_info(" elf loaded\n");
return 0;
}
-static void cleanup_tc(struct tc *tc)
-{
- unsigned long flags;
- unsigned int mtflags, vpflags;
- int tmp;
-
- local_irq_save(flags);
- mtflags = dmt();
- vpflags = dvpe();
- /* Put MVPE's into 'configuration state' */
- set_c0_mvpcontrol(MVPCONTROL_VPC);
-
- settc(tc->index);
- tmp = read_tc_c0_tcstatus();
-
- /* mark not allocated and not dynamically allocatable */
- tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
- tmp |= TCSTATUS_IXMT; /* interrupt exempt */
- write_tc_c0_tcstatus(tmp);
-
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
-
- /* bind it to anything other than VPE1 */
-// write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE
-
- clear_c0_mvpcontrol(MVPCONTROL_VPC);
- evpe(vpflags);
- emt(mtflags);
- local_irq_restore(flags);
-}
-
static int getcwd(char *buff, int size)
{
mm_segment_t old_fs;
@@ -1044,52 +765,49 @@ static int getcwd(char *buff, int size)
static int vpe_open(struct inode *inode, struct file *filp)
{
enum vpe_state state;
- struct vpe_notifications *not;
+ struct vpe_notifications *notifier;
struct vpe *v;
int ret;
- if (minor != iminor(inode)) {
+ if (VPE_MODULE_MINOR != iminor(inode)) {
/* assume only 1 device at the moment. */
- pr_warning("VPE loader: only vpe1 is supported\n");
+ pr_warn("VPE loader: only vpe1 is supported\n");
return -ENODEV;
}
- if ((v = get_vpe(tclimit)) == NULL) {
- pr_warning("VPE loader: unable to get vpe\n");
+ v = get_vpe(aprp_cpu_index());
+ if (v == NULL) {
+ pr_warn("VPE loader: unable to get vpe\n");
return -ENODEV;
}
state = xchg(&v->state, VPE_STATE_INUSE);
if (state != VPE_STATE_UNUSED) {
- printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
+ pr_debug("VPE loader: tc in use dumping regs\n");
- list_for_each_entry(not, &v->notify, list) {
- not->stop(tclimit);
- }
+ list_for_each_entry(notifier, &v->notify, list)
+ notifier->stop(aprp_cpu_index());
release_progmem(v->load_addr);
- cleanup_tc(get_tc(tclimit));
+ cleanup_tc(get_tc(aprp_cpu_index()));
}
/* this of-course trashes what was there before... */
v->pbuffer = vmalloc(P_SIZE);
if (!v->pbuffer) {
- pr_warning("VPE loader: unable to allocate memory\n");
+ pr_warn("VPE loader: unable to allocate memory\n");
return -ENOMEM;
}
v->plen = P_SIZE;
v->load_addr = NULL;
v->len = 0;
- v->uid = filp->f_cred->fsuid;
- v->gid = filp->f_cred->fsgid;
-
v->cwd[0] = 0;
ret = getcwd(v->cwd, VPE_PATH_MAX);
if (ret < 0)
- printk(KERN_WARNING "VPE loader: open, getcwd returned %d\n", ret);
+ pr_warn("VPE loader: open, getcwd returned %d\n", ret);
v->shared_ptr = NULL;
v->__start = 0;
@@ -1103,20 +821,20 @@ static int vpe_release(struct inode *inode, struct file *filp)
Elf_Ehdr *hdr;
int ret = 0;
- v = get_vpe(tclimit);
+ v = get_vpe(aprp_cpu_index());
if (v == NULL)
return -ENODEV;
hdr = (Elf_Ehdr *) v->pbuffer;
if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) == 0) {
- if (vpe_elfload(v) >= 0) {
+ if ((vpe_elfload(v) >= 0) && vpe_run) {
vpe_run(v);
} else {
- printk(KERN_WARNING "VPE loader: ELF load failed.\n");
+ pr_warn("VPE loader: ELF load failed.\n");
ret = -ENOEXEC;
}
} else {
- printk(KERN_WARNING "VPE loader: only elf files are supported\n");
+ pr_warn("VPE loader: only elf files are supported\n");
ret = -ENOEXEC;
}
@@ -1134,22 +852,22 @@ static int vpe_release(struct inode *inode, struct file *filp)
return ret;
}
-static ssize_t vpe_write(struct file *file, const char __user * buffer,
- size_t count, loff_t * ppos)
+static ssize_t vpe_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
{
size_t ret = count;
struct vpe *v;
- if (iminor(file_inode(file)) != minor)
+ if (iminor(file_inode(file)) != VPE_MODULE_MINOR)
return -ENODEV;
- v = get_vpe(tclimit);
+ v = get_vpe(aprp_cpu_index());
+
if (v == NULL)
return -ENODEV;
if ((count + v->len) > v->plen) {
- printk(KERN_WARNING
- "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
+ pr_warn("VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
return -ENOMEM;
}
@@ -1161,7 +879,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
return ret;
}
-static const struct file_operations vpe_fops = {
+const struct file_operations vpe_fops = {
.owner = THIS_MODULE,
.open = vpe_open,
.release = vpe_release,
@@ -1169,420 +887,40 @@ static const struct file_operations vpe_fops = {
.llseek = noop_llseek,
};
-/* module wrapper entry points */
-/* give me a vpe */
-vpe_handle vpe_alloc(void)
-{
- int i;
- struct vpe *v;
-
- /* find a vpe */
- for (i = 1; i < MAX_VPES; i++) {
- if ((v = get_vpe(i)) != NULL) {
- v->state = VPE_STATE_INUSE;
- return v;
- }
- }
- return NULL;
-}
-
-EXPORT_SYMBOL(vpe_alloc);
-
-/* start running from here */
-int vpe_start(vpe_handle vpe, unsigned long start)
-{
- struct vpe *v = vpe;
-
- v->__start = start;
- return vpe_run(v);
-}
-
-EXPORT_SYMBOL(vpe_start);
-
-/* halt it for now */
-int vpe_stop(vpe_handle vpe)
-{
- struct vpe *v = vpe;
- struct tc *t;
- unsigned int evpe_flags;
-
- evpe_flags = dvpe();
-
- if ((t = list_entry(v->tc.next, struct tc, tc)) != NULL) {
-
- settc(t->index);
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA);
- }
-
- evpe(evpe_flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(vpe_stop);
-
-/* I've done with it thank you */
-int vpe_free(vpe_handle vpe)
-{
- struct vpe *v = vpe;
- struct tc *t;
- unsigned int evpe_flags;
-
- if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
- return -ENOEXEC;
- }
-
- evpe_flags = dvpe();
-
- /* Put MVPE's into 'configuration state' */
- set_c0_mvpcontrol(MVPCONTROL_VPC);
-
- settc(t->index);
- write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA);
-
- /* halt the TC */
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
-
- /* mark the TC unallocated */
- write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A);
-
- v->state = VPE_STATE_UNUSED;
-
- clear_c0_mvpcontrol(MVPCONTROL_VPC);
- evpe(evpe_flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(vpe_free);
-
void *vpe_get_shared(int index)
{
- struct vpe *v;
+ struct vpe *v = get_vpe(index);
- if ((v = get_vpe(index)) == NULL)
+ if (v == NULL)
return NULL;
return v->shared_ptr;
}
-
EXPORT_SYMBOL(vpe_get_shared);
-int vpe_getuid(int index)
-{
- struct vpe *v;
-
- if ((v = get_vpe(index)) == NULL)
- return -1;
-
- return v->uid;
-}
-
-EXPORT_SYMBOL(vpe_getuid);
-
-int vpe_getgid(int index)
-{
- struct vpe *v;
-
- if ((v = get_vpe(index)) == NULL)
- return -1;
-
- return v->gid;
-}
-
-EXPORT_SYMBOL(vpe_getgid);
-
int vpe_notify(int index, struct vpe_notifications *notify)
{
- struct vpe *v;
+ struct vpe *v = get_vpe(index);
- if ((v = get_vpe(index)) == NULL)
+ if (v == NULL)
return -1;
list_add(&notify->list, &v->notify);
return 0;
}
-
EXPORT_SYMBOL(vpe_notify);
char *vpe_getcwd(int index)
{
- struct vpe *v;
+ struct vpe *v = get_vpe(index);
- if ((v = get_vpe(index)) == NULL)
+ if (v == NULL)
return NULL;
return v->cwd;
}
-
EXPORT_SYMBOL(vpe_getcwd);
-static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct vpe *vpe = get_vpe(tclimit);
- struct vpe_notifications *not;
-
- list_for_each_entry(not, &vpe->notify, list) {
- not->stop(tclimit);
- }
-
- release_progmem(vpe->load_addr);
- cleanup_tc(get_tc(tclimit));
- vpe_stop(vpe);
- vpe_free(vpe);
-
- return len;
-}
-static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill);
-
-static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr,
- char *buf)
-{
- struct vpe *vpe = get_vpe(tclimit);
-
- return sprintf(buf, "%d\n", vpe->ntcs);
-}
-
-static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct vpe *vpe = get_vpe(tclimit);
- unsigned long new;
- char *endp;
-
- new = simple_strtoul(buf, &endp, 0);
- if (endp == buf)
- goto out_einval;
-
- if (new == 0 || new > (hw_tcs - tclimit))
- goto out_einval;
-
- vpe->ntcs = new;
-
- return len;
-
-out_einval:
- return -EINVAL;
-}
-static DEVICE_ATTR_RW(ntcs);
-
-static struct attribute *vpe_attrs[] = {
- &dev_attr_kill.attr,
- &dev_attr_ntcs.attr,
- NULL,
-};
-ATTRIBUTE_GROUPS(vpe);
-
-static void vpe_device_release(struct device *cd)
-{
- kfree(cd);
-}
-
-struct class vpe_class = {
- .name = "vpe",
- .owner = THIS_MODULE,
- .dev_release = vpe_device_release,
- .dev_groups = vpe_groups,
-};
-
-struct device vpe_device;
-
-static int __init vpe_module_init(void)
-{
- unsigned int mtflags, vpflags;
- unsigned long flags, val;
- struct vpe *v = NULL;
- struct tc *t;
- int tc, err;
-
- if (!cpu_has_mipsmt) {
- printk("VPE loader: not a MIPS MT capable processor\n");
- return -ENODEV;
- }
-
- if (vpelimit == 0) {
- printk(KERN_WARNING "No VPEs reserved for AP/SP, not "
- "initializing VPE loader.\nPass maxvpes=<n> argument as "
- "kernel argument\n");
-
- return -ENODEV;
- }
-
- if (tclimit == 0) {
- printk(KERN_WARNING "No TCs reserved for AP/SP, not "
- "initializing VPE loader.\nPass maxtcs=<n> argument as "
- "kernel argument\n");
-
- return -ENODEV;
- }
-
- major = register_chrdev(0, module_name, &vpe_fops);
- if (major < 0) {
- printk("VPE loader: unable to register character device\n");
- return major;
- }
-
- err = class_register(&vpe_class);
- if (err) {
- printk(KERN_ERR "vpe_class registration failed\n");
- goto out_chrdev;
- }
-
- device_initialize(&vpe_device);
- vpe_device.class = &vpe_class,
- vpe_device.parent = NULL,
- dev_set_name(&vpe_device, "vpe1");
- vpe_device.devt = MKDEV(major, minor);
- err = device_add(&vpe_device);
- if (err) {
- printk(KERN_ERR "Adding vpe_device failed\n");
- goto out_class;
- }
-
- local_irq_save(flags);
- mtflags = dmt();
- vpflags = dvpe();
-
- /* Put MVPE's into 'configuration state' */
- set_c0_mvpcontrol(MVPCONTROL_VPC);
-
- /* dump_mtregs(); */
-
- val = read_c0_mvpconf0();
- hw_tcs = (val & MVPCONF0_PTC) + 1;
- hw_vpes = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
-
- for (tc = tclimit; tc < hw_tcs; tc++) {
- /*
- * Must re-enable multithreading temporarily or in case we
- * reschedule send IPIs or similar we might hang.
- */
- clear_c0_mvpcontrol(MVPCONTROL_VPC);
- evpe(vpflags);
- emt(mtflags);
- local_irq_restore(flags);
- t = alloc_tc(tc);
- if (!t) {
- err = -ENOMEM;
- goto out;
- }
-
- local_irq_save(flags);
- mtflags = dmt();
- vpflags = dvpe();
- set_c0_mvpcontrol(MVPCONTROL_VPC);
-
- /* VPE's */
- if (tc < hw_tcs) {
- settc(tc);
-
- if ((v = alloc_vpe(tc)) == NULL) {
- printk(KERN_WARNING "VPE: unable to allocate VPE\n");
-
- goto out_reenable;
- }
-
- v->ntcs = hw_tcs - tclimit;
-
- /* add the tc to the list of this vpe's tc's. */
- list_add(&t->tc, &v->tc);
-
- /* deactivate all but vpe0 */
- if (tc >= tclimit) {
- unsigned long tmp = read_vpe_c0_vpeconf0();
-
- tmp &= ~VPECONF0_VPA;
-
- /* master VPE */
- tmp |= VPECONF0_MVP;
- write_vpe_c0_vpeconf0(tmp);
- }
-
- /* disable multi-threading with TC's */
- write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
-
- if (tc >= vpelimit) {
- /*
- * Set config to be the same as vpe0,
- * particularly kseg0 coherency alg
- */
- write_vpe_c0_config(read_c0_config());
- }
- }
-
- /* TC's */
- t->pvpe = v; /* set the parent vpe */
-
- if (tc >= tclimit) {
- unsigned long tmp;
-
- settc(tc);
-
- /* Any TC that is bound to VPE0 gets left as is - in case
- we are running SMTC on VPE0. A TC that is bound to any
- other VPE gets bound to VPE0, ideally I'd like to make
- it homeless but it doesn't appear to let me bind a TC
- to a non-existent VPE. Which is perfectly reasonable.
-
- The (un)bound state is visible to an EJTAG probe so may
- notify GDB...
- */
-
- if (((tmp = read_tc_c0_tcbind()) & TCBIND_CURVPE)) {
- /* tc is bound >vpe0 */
- write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE);
-
- t->pvpe = get_vpe(0); /* set the parent vpe */
- }
-
- /* halt the TC */
- write_tc_c0_tchalt(TCHALT_H);
- mips_ihb();
-
- tmp = read_tc_c0_tcstatus();
-
- /* mark not activated and not dynamically allocatable */
- tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
- tmp |= TCSTATUS_IXMT; /* interrupt exempt */
- write_tc_c0_tcstatus(tmp);
- }
- }
-
-out_reenable:
- /* release config state */
- clear_c0_mvpcontrol(MVPCONTROL_VPC);
-
- evpe(vpflags);
- emt(mtflags);
- local_irq_restore(flags);
-
- return 0;
-
-out_class:
- class_unregister(&vpe_class);
-out_chrdev:
- unregister_chrdev(major, module_name);
-
-out:
- return err;
-}
-
-static void __exit vpe_module_exit(void)
-{
- struct vpe *v, *n;
-
- device_del(&vpe_device);
- unregister_chrdev(major, module_name);
-
- /* No locking needed here */
- list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) {
- if (v->state != VPE_STATE_UNUSED)
- release_vpe(v);
- }
-}
-
module_init(vpe_module_init);
module_exit(vpe_module_exit);
MODULE_DESCRIPTION("MIPS VPE Loader");
diff --git a/arch/mips/kvm/kvm_locore.S b/arch/mips/kvm/kvm_locore.S
index bbace092ad0..033ac343e72 100644
--- a/arch/mips/kvm/kvm_locore.S
+++ b/arch/mips/kvm/kvm_locore.S
@@ -611,35 +611,3 @@ MIPSX(exceptions):
.word _C_LABEL(MIPSX(GuestException)) # 29
.word _C_LABEL(MIPSX(GuestException)) # 30
.word _C_LABEL(MIPSX(GuestException)) # 31
-
-
-/* This routine makes changes to the instruction stream effective to the hardware.
- * It should be called after the instruction stream is written.
- * On return, the new instructions are effective.
- * Inputs:
- * a0 = Start address of new instruction stream
- * a1 = Size, in bytes, of new instruction stream
- */
-
-#define HW_SYNCI_Step $1
-LEAF(MIPSX(SyncICache))
- .set push
- .set mips32r2
- beq a1, zero, 20f
- nop
- REG_ADDU a1, a0, a1
- rdhwr v0, HW_SYNCI_Step
- beq v0, zero, 20f
- nop
-10:
- synci 0(a0)
- REG_ADDU a0, a0, v0
- sltu v1, a0, a1
- bne v1, zero, 10b
- nop
- sync
-20:
- jr.hb ra
- nop
- .set pop
-END(MIPSX(SyncICache))
diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c
index a7b044536de..f3c56a182fd 100644
--- a/arch/mips/kvm/kvm_mips.c
+++ b/arch/mips/kvm/kvm_mips.c
@@ -61,11 +61,6 @@ static int kvm_mips_reset_vcpu(struct kvm_vcpu *vcpu)
return 0;
}
-gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
-{
- return gfn;
-}
-
/* XXXKYMA: We are simulatoring a processor that has the WII bit set in Config7, so we
* are "runnable" if interrupts are pending
*/
@@ -130,8 +125,8 @@ static void kvm_mips_init_vm_percpu(void *arg)
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
if (atomic_inc_return(&kvm_mips_instance) == 1) {
- kvm_info("%s: 1st KVM instance, setup host TLB parameters\n",
- __func__);
+ kvm_debug("%s: 1st KVM instance, setup host TLB parameters\n",
+ __func__);
on_each_cpu(kvm_mips_init_vm_percpu, kvm, 1);
}
@@ -149,9 +144,7 @@ void kvm_mips_free_vcpus(struct kvm *kvm)
if (kvm->arch.guest_pmap[i] != KVM_INVALID_PAGE)
kvm_mips_release_pfn_clean(kvm->arch.guest_pmap[i]);
}
-
- if (kvm->arch.guest_pmap)
- kfree(kvm->arch.guest_pmap);
+ kfree(kvm->arch.guest_pmap);
kvm_for_each_vcpu(i, vcpu, kvm) {
kvm_arch_vcpu_free(vcpu);
@@ -186,8 +179,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
/* If this is the last instance, restore wired count */
if (atomic_dec_return(&kvm_mips_instance) == 0) {
- kvm_info("%s: last KVM instance, restoring TLB parameters\n",
- __func__);
+ kvm_debug("%s: last KVM instance, restoring TLB parameters\n",
+ __func__);
on_each_cpu(kvm_mips_uninit_tlbs, NULL, 1);
}
}
@@ -198,12 +191,13 @@ kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
return -ENOIOCTLCMD;
}
-void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
struct kvm_memory_slot *dont)
{
}
-int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
+ unsigned long npages)
{
return 0;
}
@@ -248,9 +242,8 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
goto out;
}
- kvm_info
- ("Allocated space for Guest PMAP Table (%ld pages) @ %p\n",
- npages, kvm->arch.guest_pmap);
+ kvm_debug("Allocated space for Guest PMAP Table (%ld pages) @ %p\n",
+ npages, kvm->arch.guest_pmap);
/* Now setup the page table */
for (i = 0; i < npages; i++) {
@@ -295,7 +288,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
if (err)
goto out_free_cpu;
- kvm_info("kvm @ %p: create cpu %d at %p\n", kvm, id, vcpu);
+ kvm_debug("kvm @ %p: create cpu %d at %p\n", kvm, id, vcpu);
/* Allocate space for host mode exception handlers that handle
* guest mode exits
@@ -303,7 +296,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
if (cpu_has_veic || cpu_has_vint) {
size = 0x200 + VECTORSPACING * 64;
} else {
- size = 0x200;
+ size = 0x4000;
}
/* Save Linux EBASE */
@@ -315,8 +308,8 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
err = -ENOMEM;
goto out_free_cpu;
}
- kvm_info("Allocated %d bytes for KVM Exception Handlers @ %p\n",
- ALIGN(size, PAGE_SIZE), gebase);
+ kvm_debug("Allocated %d bytes for KVM Exception Handlers @ %p\n",
+ ALIGN(size, PAGE_SIZE), gebase);
/* Save new ebase */
vcpu->arch.guest_ebase = gebase;
@@ -341,15 +334,16 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
/* General handler, relocate to unmapped space for sanity's sake */
offset = 0x2000;
- kvm_info("Installing KVM Exception handlers @ %p, %#x bytes\n",
- gebase + offset,
- mips32_GuestExceptionEnd - mips32_GuestException);
+ kvm_debug("Installing KVM Exception handlers @ %p, %#x bytes\n",
+ gebase + offset,
+ mips32_GuestExceptionEnd - mips32_GuestException);
memcpy(gebase + offset, mips32_GuestException,
mips32_GuestExceptionEnd - mips32_GuestException);
/* Invalidate the icache for these ranges */
- mips32_SyncICache((unsigned long) gebase, ALIGN(size, PAGE_SIZE));
+ local_flush_icache_range((unsigned long)gebase,
+ (unsigned long)gebase + ALIGN(size, PAGE_SIZE));
/* Allocate comm page for guest kernel, a TLB will be reserved for mapping GVA @ 0xFFFF8000 to this page */
vcpu->arch.kseg0_commpage = kzalloc(PAGE_SIZE << 1, GFP_KERNEL);
@@ -359,14 +353,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
goto out_free_gebase;
}
- kvm_info("Allocated COMM page @ %p\n", vcpu->arch.kseg0_commpage);
+ kvm_debug("Allocated COMM page @ %p\n", vcpu->arch.kseg0_commpage);
kvm_mips_commpage_init(vcpu);
/* Init */
vcpu->arch.last_sched_cpu = -1;
/* Start off the timer */
- kvm_mips_emulate_count(vcpu);
+ kvm_mips_init_count(vcpu);
return vcpu;
@@ -388,12 +382,9 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
kvm_mips_dump_stats(vcpu);
- if (vcpu->arch.guest_ebase)
- kfree(vcpu->arch.guest_ebase);
-
- if (vcpu->arch.kseg0_commpage)
- kfree(vcpu->arch.kseg0_commpage);
-
+ kfree(vcpu->arch.guest_ebase);
+ kfree(vcpu->arch.kseg0_commpage);
+ kfree(vcpu);
}
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -422,11 +413,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
vcpu->mmio_needed = 0;
}
+ local_irq_disable();
/* Check if we have any exceptions/interrupts pending */
kvm_mips_deliver_interrupts(vcpu,
kvm_read_c0_guest_cause(vcpu->arch.cop0));
- local_irq_disable();
kvm_guest_enter();
r = __kvm_mips_vcpu_run(run, vcpu);
@@ -489,36 +480,6 @@ kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
return -ENOIOCTLCMD;
}
-#define MIPS_CP0_32(_R, _S) \
- (KVM_REG_MIPS | KVM_REG_SIZE_U32 | 0x10000 | (8 * (_R) + (_S)))
-
-#define MIPS_CP0_64(_R, _S) \
- (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0x10000 | (8 * (_R) + (_S)))
-
-#define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0)
-#define KVM_REG_MIPS_CP0_ENTRYLO0 MIPS_CP0_64(2, 0)
-#define KVM_REG_MIPS_CP0_ENTRYLO1 MIPS_CP0_64(3, 0)
-#define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0)
-#define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2)
-#define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0)
-#define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1)
-#define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0)
-#define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0)
-#define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0)
-#define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0)
-#define KVM_REG_MIPS_CP0_ENTRYHI MIPS_CP0_64(10, 0)
-#define KVM_REG_MIPS_CP0_COMPARE MIPS_CP0_32(11, 0)
-#define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0)
-#define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0)
-#define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1)
-#define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0)
-#define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1)
-#define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2)
-#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3)
-#define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7)
-#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0)
-#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0)
-
static u64 kvm_mips_get_one_regs[] = {
KVM_REG_MIPS_R0,
KVM_REG_MIPS_R1,
@@ -559,25 +520,34 @@ static u64 kvm_mips_get_one_regs[] = {
KVM_REG_MIPS_CP0_INDEX,
KVM_REG_MIPS_CP0_CONTEXT,
+ KVM_REG_MIPS_CP0_USERLOCAL,
KVM_REG_MIPS_CP0_PAGEMASK,
KVM_REG_MIPS_CP0_WIRED,
+ KVM_REG_MIPS_CP0_HWRENA,
KVM_REG_MIPS_CP0_BADVADDR,
+ KVM_REG_MIPS_CP0_COUNT,
KVM_REG_MIPS_CP0_ENTRYHI,
+ KVM_REG_MIPS_CP0_COMPARE,
KVM_REG_MIPS_CP0_STATUS,
KVM_REG_MIPS_CP0_CAUSE,
- /* EPC set via kvm_regs, et al. */
+ KVM_REG_MIPS_CP0_EPC,
KVM_REG_MIPS_CP0_CONFIG,
KVM_REG_MIPS_CP0_CONFIG1,
KVM_REG_MIPS_CP0_CONFIG2,
KVM_REG_MIPS_CP0_CONFIG3,
KVM_REG_MIPS_CP0_CONFIG7,
- KVM_REG_MIPS_CP0_ERROREPC
+ KVM_REG_MIPS_CP0_ERROREPC,
+
+ KVM_REG_MIPS_COUNT_CTL,
+ KVM_REG_MIPS_COUNT_RESUME,
+ KVM_REG_MIPS_COUNT_HZ,
};
static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
+ int ret;
s64 v;
switch (reg->id) {
@@ -600,24 +570,36 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
case KVM_REG_MIPS_CP0_CONTEXT:
v = (long)kvm_read_c0_guest_context(cop0);
break;
+ case KVM_REG_MIPS_CP0_USERLOCAL:
+ v = (long)kvm_read_c0_guest_userlocal(cop0);
+ break;
case KVM_REG_MIPS_CP0_PAGEMASK:
v = (long)kvm_read_c0_guest_pagemask(cop0);
break;
case KVM_REG_MIPS_CP0_WIRED:
v = (long)kvm_read_c0_guest_wired(cop0);
break;
+ case KVM_REG_MIPS_CP0_HWRENA:
+ v = (long)kvm_read_c0_guest_hwrena(cop0);
+ break;
case KVM_REG_MIPS_CP0_BADVADDR:
v = (long)kvm_read_c0_guest_badvaddr(cop0);
break;
case KVM_REG_MIPS_CP0_ENTRYHI:
v = (long)kvm_read_c0_guest_entryhi(cop0);
break;
+ case KVM_REG_MIPS_CP0_COMPARE:
+ v = (long)kvm_read_c0_guest_compare(cop0);
+ break;
case KVM_REG_MIPS_CP0_STATUS:
v = (long)kvm_read_c0_guest_status(cop0);
break;
case KVM_REG_MIPS_CP0_CAUSE:
v = (long)kvm_read_c0_guest_cause(cop0);
break;
+ case KVM_REG_MIPS_CP0_EPC:
+ v = (long)kvm_read_c0_guest_epc(cop0);
+ break;
case KVM_REG_MIPS_CP0_ERROREPC:
v = (long)kvm_read_c0_guest_errorepc(cop0);
break;
@@ -636,6 +618,15 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
case KVM_REG_MIPS_CP0_CONFIG7:
v = (long)kvm_read_c0_guest_config7(cop0);
break;
+ /* registers to be handled specially */
+ case KVM_REG_MIPS_CP0_COUNT:
+ case KVM_REG_MIPS_COUNT_CTL:
+ case KVM_REG_MIPS_COUNT_RESUME:
+ case KVM_REG_MIPS_COUNT_HZ:
+ ret = kvm_mips_callbacks->get_one_reg(vcpu, reg, &v);
+ if (ret)
+ return ret;
+ break;
default:
return -EINVAL;
}
@@ -696,12 +687,18 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
case KVM_REG_MIPS_CP0_CONTEXT:
kvm_write_c0_guest_context(cop0, v);
break;
+ case KVM_REG_MIPS_CP0_USERLOCAL:
+ kvm_write_c0_guest_userlocal(cop0, v);
+ break;
case KVM_REG_MIPS_CP0_PAGEMASK:
kvm_write_c0_guest_pagemask(cop0, v);
break;
case KVM_REG_MIPS_CP0_WIRED:
kvm_write_c0_guest_wired(cop0, v);
break;
+ case KVM_REG_MIPS_CP0_HWRENA:
+ kvm_write_c0_guest_hwrena(cop0, v);
+ break;
case KVM_REG_MIPS_CP0_BADVADDR:
kvm_write_c0_guest_badvaddr(cop0, v);
break;
@@ -711,12 +708,20 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
case KVM_REG_MIPS_CP0_STATUS:
kvm_write_c0_guest_status(cop0, v);
break;
- case KVM_REG_MIPS_CP0_CAUSE:
- kvm_write_c0_guest_cause(cop0, v);
+ case KVM_REG_MIPS_CP0_EPC:
+ kvm_write_c0_guest_epc(cop0, v);
break;
case KVM_REG_MIPS_CP0_ERROREPC:
kvm_write_c0_guest_errorepc(cop0, v);
break;
+ /* registers to be handled specially */
+ case KVM_REG_MIPS_CP0_COUNT:
+ case KVM_REG_MIPS_CP0_COMPARE:
+ case KVM_REG_MIPS_CP0_CAUSE:
+ case KVM_REG_MIPS_COUNT_CTL:
+ case KVM_REG_MIPS_COUNT_RESUME:
+ case KVM_REG_MIPS_COUNT_HZ:
+ return kvm_mips_callbacks->set_one_reg(vcpu, reg, v);
default:
return -EINVAL;
}
@@ -919,7 +924,7 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)
return -1;
printk("VCPU Register Dump:\n");
- printk("\tpc = 0x%08lx\n", vcpu->arch.pc);;
+ printk("\tpc = 0x%08lx\n", vcpu->arch.pc);
printk("\texceptions: %08lx\n", vcpu->arch.pending_exceptions);
for (i = 0; i < 32; i += 4) {
@@ -968,7 +973,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
return 0;
}
-void kvm_mips_comparecount_func(unsigned long data)
+static void kvm_mips_comparecount_func(unsigned long data)
{
struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
@@ -983,15 +988,13 @@ void kvm_mips_comparecount_func(unsigned long data)
/*
* low level hrtimer wake routine.
*/
-enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer)
+static enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer)
{
struct kvm_vcpu *vcpu;
vcpu = container_of(timer, struct kvm_vcpu, arch.comparecount_timer);
kvm_mips_comparecount_func((unsigned long) vcpu);
- hrtimer_forward_now(&vcpu->arch.comparecount_timer,
- ktime_set(0, MS_TO_NS(10)));
- return HRTIMER_RESTART;
+ return kvm_mips_count_timeout(vcpu);
}
int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
@@ -1000,7 +1003,6 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
hrtimer_init(&vcpu->arch.comparecount_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
vcpu->arch.comparecount_timer.function = kvm_mips_comparecount_wakeup;
- kvm_mips_init_shadow_tlb(vcpu);
return 0;
}
diff --git a/arch/mips/kvm/kvm_mips_dyntrans.c b/arch/mips/kvm/kvm_mips_dyntrans.c
index 96528e2d1ea..b80e41d858f 100644
--- a/arch/mips/kvm/kvm_mips_dyntrans.c
+++ b/arch/mips/kvm/kvm_mips_dyntrans.c
@@ -16,6 +16,7 @@
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/bootmem.h>
+#include <asm/cacheflush.h>
#include "kvm_mips_comm.h"
@@ -40,7 +41,7 @@ kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
(vcpu, (unsigned long) opc));
memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
- mips32_SyncICache(kseg0_opc, 32);
+ local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
return result;
}
@@ -66,7 +67,7 @@ kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
(vcpu, (unsigned long) opc));
memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t));
- mips32_SyncICache(kseg0_opc, 32);
+ local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
return result;
}
@@ -99,11 +100,12 @@ kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
(vcpu, (unsigned long) opc));
memcpy((void *)kseg0_opc, (void *)&mfc0_inst, sizeof(uint32_t));
- mips32_SyncICache(kseg0_opc, 32);
+ local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
local_irq_save(flags);
memcpy((void *)opc, (void *)&mfc0_inst, sizeof(uint32_t));
- mips32_SyncICache((unsigned long) opc, 32);
+ local_flush_icache_range((unsigned long)opc,
+ (unsigned long)opc + 32);
local_irq_restore(flags);
} else {
kvm_err("%s: Invalid address: %p\n", __func__, opc);
@@ -134,11 +136,12 @@ kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa
(vcpu, (unsigned long) opc));
memcpy((void *)kseg0_opc, (void *)&mtc0_inst, sizeof(uint32_t));
- mips32_SyncICache(kseg0_opc, 32);
+ local_flush_icache_range(kseg0_opc, kseg0_opc + 32);
} else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) {
local_irq_save(flags);
memcpy((void *)opc, (void *)&mtc0_inst, sizeof(uint32_t));
- mips32_SyncICache((unsigned long) opc, 32);
+ local_flush_icache_range((unsigned long)opc,
+ (unsigned long)opc + 32);
local_irq_restore(flags);
} else {
kvm_err("%s: Invalid address: %p\n", __func__, opc);
diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
index 4b6274b47f3..8d484009008 100644
--- a/arch/mips/kvm/kvm_mips_emul.c
+++ b/arch/mips/kvm/kvm_mips_emul.c
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/ktime.h>
#include <linux/kvm_host.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
@@ -228,25 +229,520 @@ enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause)
return er;
}
-/* Everytime the compare register is written to, we need to decide when to fire
- * the timer that represents timer ticks to the GUEST.
+/**
+ * kvm_mips_count_disabled() - Find whether the CP0_Count timer is disabled.
+ * @vcpu: Virtual CPU.
*
+ * Returns: 1 if the CP0_Count timer is disabled by either the guest
+ * CP0_Cause.DC bit or the count_ctl.DC bit.
+ * 0 otherwise (in which case CP0_Count timer is running).
*/
-enum emulation_result kvm_mips_emulate_count(struct kvm_vcpu *vcpu)
+static inline int kvm_mips_count_disabled(struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
- enum emulation_result er = EMULATE_DONE;
+ return (vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) ||
+ (kvm_read_c0_guest_cause(cop0) & CAUSEF_DC);
+}
+
+/**
+ * kvm_mips_ktime_to_count() - Scale ktime_t to a 32-bit count.
+ *
+ * Caches the dynamic nanosecond bias in vcpu->arch.count_dyn_bias.
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ */
+static uint32_t kvm_mips_ktime_to_count(struct kvm_vcpu *vcpu, ktime_t now)
+{
+ s64 now_ns, periods;
+ u64 delta;
+
+ now_ns = ktime_to_ns(now);
+ delta = now_ns + vcpu->arch.count_dyn_bias;
+
+ if (delta >= vcpu->arch.count_period) {
+ /* If delta is out of safe range the bias needs adjusting */
+ periods = div64_s64(now_ns, vcpu->arch.count_period);
+ vcpu->arch.count_dyn_bias = -periods * vcpu->arch.count_period;
+ /* Recalculate delta with new bias */
+ delta = now_ns + vcpu->arch.count_dyn_bias;
+ }
+
+ /*
+ * We've ensured that:
+ * delta < count_period
+ *
+ * Therefore the intermediate delta*count_hz will never overflow since
+ * at the boundary condition:
+ * delta = count_period
+ * delta = NSEC_PER_SEC * 2^32 / count_hz
+ * delta * count_hz = NSEC_PER_SEC * 2^32
+ */
+ return div_u64(delta * vcpu->arch.count_hz, NSEC_PER_SEC);
+}
+
+/**
+ * kvm_mips_count_time() - Get effective current time.
+ * @vcpu: Virtual CPU.
+ *
+ * Get effective monotonic ktime. This is usually a straightforward ktime_get(),
+ * except when the master disable bit is set in count_ctl, in which case it is
+ * count_resume, i.e. the time that the count was disabled.
+ *
+ * Returns: Effective monotonic ktime for CP0_Count.
+ */
+static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu)
+{
+ if (unlikely(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC))
+ return vcpu->arch.count_resume;
+
+ return ktime_get();
+}
+
+/**
+ * kvm_mips_read_count_running() - Read the current count value as if running.
+ * @vcpu: Virtual CPU.
+ * @now: Kernel time to read CP0_Count at.
+ *
+ * Returns the current guest CP0_Count register at time @now and handles if the
+ * timer interrupt is pending and hasn't been handled yet.
+ *
+ * Returns: The current value of the guest CP0_Count register.
+ */
+static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
+{
+ ktime_t expires;
+ int running;
- /* If COUNT is enabled */
- if (!(kvm_read_c0_guest_cause(cop0) & CAUSEF_DC)) {
- hrtimer_try_to_cancel(&vcpu->arch.comparecount_timer);
- hrtimer_start(&vcpu->arch.comparecount_timer,
- ktime_set(0, MS_TO_NS(10)), HRTIMER_MODE_REL);
+ /* Is the hrtimer pending? */
+ expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
+ if (ktime_compare(now, expires) >= 0) {
+ /*
+ * Cancel it while we handle it so there's no chance of
+ * interference with the timeout handler.
+ */
+ running = hrtimer_cancel(&vcpu->arch.comparecount_timer);
+
+ /* Nothing should be waiting on the timeout */
+ kvm_mips_callbacks->queue_timer_int(vcpu);
+
+ /*
+ * Restart the timer if it was running based on the expiry time
+ * we read, so that we don't push it back 2 periods.
+ */
+ if (running) {
+ expires = ktime_add_ns(expires,
+ vcpu->arch.count_period);
+ hrtimer_start(&vcpu->arch.comparecount_timer, expires,
+ HRTIMER_MODE_ABS);
+ }
+ }
+
+ /* Return the biased and scaled guest CP0_Count */
+ return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+}
+
+/**
+ * kvm_mips_read_count() - Read the current count value.
+ * @vcpu: Virtual CPU.
+ *
+ * Read the current guest CP0_Count value, taking into account whether the timer
+ * is stopped.
+ *
+ * Returns: The current guest CP0_Count value.
+ */
+uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+ /* If count disabled just read static copy of count */
+ if (kvm_mips_count_disabled(vcpu))
+ return kvm_read_c0_guest_count(cop0);
+
+ return kvm_mips_read_count_running(vcpu, ktime_get());
+}
+
+/**
+ * kvm_mips_freeze_hrtimer() - Safely stop the hrtimer.
+ * @vcpu: Virtual CPU.
+ * @count: Output pointer for CP0_Count value at point of freeze.
+ *
+ * Freeze the hrtimer safely and return both the ktime and the CP0_Count value
+ * at the point it was frozen. It is guaranteed that any pending interrupts at
+ * the point it was frozen are handled, and none after that point.
+ *
+ * This is useful where the time/CP0_Count is needed in the calculation of the
+ * new parameters.
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ *
+ * Returns: The ktime at the point of freeze.
+ */
+static ktime_t kvm_mips_freeze_hrtimer(struct kvm_vcpu *vcpu,
+ uint32_t *count)
+{
+ ktime_t now;
+
+ /* stop hrtimer before finding time */
+ hrtimer_cancel(&vcpu->arch.comparecount_timer);
+ now = ktime_get();
+
+ /* find count at this point and handle pending hrtimer */
+ *count = kvm_mips_read_count_running(vcpu, now);
+
+ return now;
+}
+
+
+/**
+ * kvm_mips_resume_hrtimer() - Resume hrtimer, updating expiry.
+ * @vcpu: Virtual CPU.
+ * @now: ktime at point of resume.
+ * @count: CP0_Count at point of resume.
+ *
+ * Resumes the timer and updates the timer expiry based on @now and @count.
+ * This can be used in conjunction with kvm_mips_freeze_timer() when timer
+ * parameters need to be changed.
+ *
+ * It is guaranteed that a timer interrupt immediately after resume will be
+ * handled, but not if CP_Compare is exactly at @count. That case is already
+ * handled by kvm_mips_freeze_timer().
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ */
+static void kvm_mips_resume_hrtimer(struct kvm_vcpu *vcpu,
+ ktime_t now, uint32_t count)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ uint32_t compare;
+ u64 delta;
+ ktime_t expire;
+
+ /* Calculate timeout (wrap 0 to 2^32) */
+ compare = kvm_read_c0_guest_compare(cop0);
+ delta = (u64)(uint32_t)(compare - count - 1) + 1;
+ delta = div_u64(delta * NSEC_PER_SEC, vcpu->arch.count_hz);
+ expire = ktime_add_ns(now, delta);
+
+ /* Update hrtimer to use new timeout */
+ hrtimer_cancel(&vcpu->arch.comparecount_timer);
+ hrtimer_start(&vcpu->arch.comparecount_timer, expire, HRTIMER_MODE_ABS);
+}
+
+/**
+ * kvm_mips_update_hrtimer() - Update next expiry time of hrtimer.
+ * @vcpu: Virtual CPU.
+ *
+ * Recalculates and updates the expiry time of the hrtimer. This can be used
+ * after timer parameters have been altered which do not depend on the time that
+ * the change occurs (in those cases kvm_mips_freeze_hrtimer() and
+ * kvm_mips_resume_hrtimer() are used directly).
+ *
+ * It is guaranteed that no timer interrupts will be lost in the process.
+ *
+ * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
+ */
+static void kvm_mips_update_hrtimer(struct kvm_vcpu *vcpu)
+{
+ ktime_t now;
+ uint32_t count;
+
+ /*
+ * freeze_hrtimer takes care of a timer interrupts <= count, and
+ * resume_hrtimer the hrtimer takes care of a timer interrupts > count.
+ */
+ now = kvm_mips_freeze_hrtimer(vcpu, &count);
+ kvm_mips_resume_hrtimer(vcpu, now, count);
+}
+
+/**
+ * kvm_mips_write_count() - Modify the count and update timer.
+ * @vcpu: Virtual CPU.
+ * @count: Guest CP0_Count value to set.
+ *
+ * Sets the CP0_Count value and updates the timer accordingly.
+ */
+void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ ktime_t now;
+
+ /* Calculate bias */
+ now = kvm_mips_count_time(vcpu);
+ vcpu->arch.count_bias = count - kvm_mips_ktime_to_count(vcpu, now);
+
+ if (kvm_mips_count_disabled(vcpu))
+ /* The timer's disabled, adjust the static count */
+ kvm_write_c0_guest_count(cop0, count);
+ else
+ /* Update timeout */
+ kvm_mips_resume_hrtimer(vcpu, now, count);
+}
+
+/**
+ * kvm_mips_init_count() - Initialise timer.
+ * @vcpu: Virtual CPU.
+ *
+ * Initialise the timer to a sensible frequency, namely 100MHz, zero it, and set
+ * it going if it's enabled.
+ */
+void kvm_mips_init_count(struct kvm_vcpu *vcpu)
+{
+ /* 100 MHz */
+ vcpu->arch.count_hz = 100*1000*1000;
+ vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32,
+ vcpu->arch.count_hz);
+ vcpu->arch.count_dyn_bias = 0;
+
+ /* Starting at 0 */
+ kvm_mips_write_count(vcpu, 0);
+}
+
+/**
+ * kvm_mips_set_count_hz() - Update the frequency of the timer.
+ * @vcpu: Virtual CPU.
+ * @count_hz: Frequency of CP0_Count timer in Hz.
+ *
+ * Change the frequency of the CP0_Count timer. This is done atomically so that
+ * CP0_Count is continuous and no timer interrupt is lost.
+ *
+ * Returns: -EINVAL if @count_hz is out of range.
+ * 0 on success.
+ */
+int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ int dc;
+ ktime_t now;
+ u32 count;
+
+ /* ensure the frequency is in a sensible range... */
+ if (count_hz <= 0 || count_hz > NSEC_PER_SEC)
+ return -EINVAL;
+ /* ... and has actually changed */
+ if (vcpu->arch.count_hz == count_hz)
+ return 0;
+
+ /* Safely freeze timer so we can keep it continuous */
+ dc = kvm_mips_count_disabled(vcpu);
+ if (dc) {
+ now = kvm_mips_count_time(vcpu);
+ count = kvm_read_c0_guest_count(cop0);
} else {
- hrtimer_try_to_cancel(&vcpu->arch.comparecount_timer);
+ now = kvm_mips_freeze_hrtimer(vcpu, &count);
}
- return er;
+ /* Update the frequency */
+ vcpu->arch.count_hz = count_hz;
+ vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32, count_hz);
+ vcpu->arch.count_dyn_bias = 0;
+
+ /* Calculate adjusted bias so dynamic count is unchanged */
+ vcpu->arch.count_bias = count - kvm_mips_ktime_to_count(vcpu, now);
+
+ /* Update and resume hrtimer */
+ if (!dc)
+ kvm_mips_resume_hrtimer(vcpu, now, count);
+ return 0;
+}
+
+/**
+ * kvm_mips_write_compare() - Modify compare and update timer.
+ * @vcpu: Virtual CPU.
+ * @compare: New CP0_Compare value.
+ *
+ * Update CP0_Compare to a new value and update the timeout.
+ */
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+ /* if unchanged, must just be an ack */
+ if (kvm_read_c0_guest_compare(cop0) == compare)
+ return;
+
+ /* Update compare */
+ kvm_write_c0_guest_compare(cop0, compare);
+
+ /* Update timeout if count enabled */
+ if (!kvm_mips_count_disabled(vcpu))
+ kvm_mips_update_hrtimer(vcpu);
+}
+
+/**
+ * kvm_mips_count_disable() - Disable count.
+ * @vcpu: Virtual CPU.
+ *
+ * Disable the CP0_Count timer. A timer interrupt on or before the final stop
+ * time will be handled but not after.
+ *
+ * Assumes CP0_Count was previously enabled but now Guest.CP0_Cause.DC or
+ * count_ctl.DC has been set (count disabled).
+ *
+ * Returns: The time that the timer was stopped.
+ */
+static ktime_t kvm_mips_count_disable(struct kvm_vcpu *vcpu)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ uint32_t count;
+ ktime_t now;
+
+ /* Stop hrtimer */
+ hrtimer_cancel(&vcpu->arch.comparecount_timer);
+
+ /* Set the static count from the dynamic count, handling pending TI */
+ now = ktime_get();
+ count = kvm_mips_read_count_running(vcpu, now);
+ kvm_write_c0_guest_count(cop0, count);
+
+ return now;
+}
+
+/**
+ * kvm_mips_count_disable_cause() - Disable count using CP0_Cause.DC.
+ * @vcpu: Virtual CPU.
+ *
+ * Disable the CP0_Count timer and set CP0_Cause.DC. A timer interrupt on or
+ * before the final stop time will be handled if the timer isn't disabled by
+ * count_ctl.DC, but not after.
+ *
+ * Assumes CP0_Cause.DC is clear (count enabled).
+ */
+void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+
+ kvm_set_c0_guest_cause(cop0, CAUSEF_DC);
+ if (!(vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC))
+ kvm_mips_count_disable(vcpu);
+}
+
+/**
+ * kvm_mips_count_enable_cause() - Enable count using CP0_Cause.DC.
+ * @vcpu: Virtual CPU.
+ *
+ * Enable the CP0_Count timer and clear CP0_Cause.DC. A timer interrupt after
+ * the start time will be handled if the timer isn't disabled by count_ctl.DC,
+ * potentially before even returning, so the caller should be careful with
+ * ordering of CP0_Cause modifications so as not to lose it.
+ *
+ * Assumes CP0_Cause.DC is set (count disabled).
+ */
+void kvm_mips_count_enable_cause(struct kvm_vcpu *vcpu)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ uint32_t count;
+
+ kvm_clear_c0_guest_cause(cop0, CAUSEF_DC);
+
+ /*
+ * Set the dynamic count to match the static count.
+ * This starts the hrtimer if count_ctl.DC allows it.
+ * Otherwise it conveniently updates the biases.
+ */
+ count = kvm_read_c0_guest_count(cop0);
+ kvm_mips_write_count(vcpu, count);
+}
+
+/**
+ * kvm_mips_set_count_ctl() - Update the count control KVM register.
+ * @vcpu: Virtual CPU.
+ * @count_ctl: Count control register new value.
+ *
+ * Set the count control KVM register. The timer is updated accordingly.
+ *
+ * Returns: -EINVAL if reserved bits are set.
+ * 0 on success.
+ */
+int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ s64 changed = count_ctl ^ vcpu->arch.count_ctl;
+ s64 delta;
+ ktime_t expire, now;
+ uint32_t count, compare;
+
+ /* Only allow defined bits to be changed */
+ if (changed & ~(s64)(KVM_REG_MIPS_COUNT_CTL_DC))
+ return -EINVAL;
+
+ /* Apply new value */
+ vcpu->arch.count_ctl = count_ctl;
+
+ /* Master CP0_Count disable */
+ if (changed & KVM_REG_MIPS_COUNT_CTL_DC) {
+ /* Is CP0_Cause.DC already disabling CP0_Count? */
+ if (kvm_read_c0_guest_cause(cop0) & CAUSEF_DC) {
+ if (count_ctl & KVM_REG_MIPS_COUNT_CTL_DC)
+ /* Just record the current time */
+ vcpu->arch.count_resume = ktime_get();
+ } else if (count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) {
+ /* disable timer and record current time */
+ vcpu->arch.count_resume = kvm_mips_count_disable(vcpu);
+ } else {
+ /*
+ * Calculate timeout relative to static count at resume
+ * time (wrap 0 to 2^32).
+ */
+ count = kvm_read_c0_guest_count(cop0);
+ compare = kvm_read_c0_guest_compare(cop0);
+ delta = (u64)(uint32_t)(compare - count - 1) + 1;
+ delta = div_u64(delta * NSEC_PER_SEC,
+ vcpu->arch.count_hz);
+ expire = ktime_add_ns(vcpu->arch.count_resume, delta);
+
+ /* Handle pending interrupt */
+ now = ktime_get();
+ if (ktime_compare(now, expire) >= 0)
+ /* Nothing should be waiting on the timeout */
+ kvm_mips_callbacks->queue_timer_int(vcpu);
+
+ /* Resume hrtimer without changing bias */
+ count = kvm_mips_read_count_running(vcpu, now);
+ kvm_mips_resume_hrtimer(vcpu, now, count);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * kvm_mips_set_count_resume() - Update the count resume KVM register.
+ * @vcpu: Virtual CPU.
+ * @count_resume: Count resume register new value.
+ *
+ * Set the count resume KVM register.
+ *
+ * Returns: -EINVAL if out of valid range (0..now).
+ * 0 on success.
+ */
+int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume)
+{
+ /*
+ * It doesn't make sense for the resume time to be in the future, as it
+ * would be possible for the next interrupt to be more than a full
+ * period in the future.
+ */
+ if (count_resume < 0 || count_resume > ktime_to_ns(ktime_get()))
+ return -EINVAL;
+
+ vcpu->arch.count_resume = ns_to_ktime(count_resume);
+ return 0;
+}
+
+/**
+ * kvm_mips_count_timeout() - Push timer forward on timeout.
+ * @vcpu: Virtual CPU.
+ *
+ * Handle an hrtimer event by push the hrtimer forward a period.
+ *
+ * Returns: The hrtimer_restart value to return to the hrtimer subsystem.
+ */
+enum hrtimer_restart kvm_mips_count_timeout(struct kvm_vcpu *vcpu)
+{
+ /* Add the Count period to the current expiry time */
+ hrtimer_add_expires_ns(&vcpu->arch.comparecount_timer,
+ vcpu->arch.count_period);
+ return HRTIMER_RESTART;
}
enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
@@ -436,13 +932,6 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
sel = inst & 0x7;
co_bit = (inst >> 25) & 1;
- /* Verify that the register is valid */
- if (rd > MIPS_CP0_DESAVE) {
- printk("Invalid rd: %d\n", rd);
- er = EMULATE_FAIL;
- goto done;
- }
-
if (co_bit) {
op = (inst) & 0xff;
@@ -478,8 +967,7 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
#endif
/* Get reg */
if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
- /* XXXKYMA: Run the Guest count register @ 1/4 the rate of the host */
- vcpu->arch.gprs[rt] = (read_c0_count() >> 2);
+ vcpu->arch.gprs[rt] = kvm_mips_read_count(vcpu);
} else if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) {
vcpu->arch.gprs[rt] = 0x0;
#ifdef CONFIG_KVM_MIPS_DYN_TRANS
@@ -546,10 +1034,7 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
}
/* Are we writing to COUNT */
else if ((rd == MIPS_CP0_COUNT) && (sel == 0)) {
- /* Linux doesn't seem to write into COUNT, we throw an error
- * if we notice a write to COUNT
- */
- /*er = EMULATE_FAIL; */
+ kvm_mips_write_count(vcpu, vcpu->arch.gprs[rt]);
goto done;
} else if ((rd == MIPS_CP0_COMPARE) && (sel == 0)) {
kvm_debug("[%#x] MTCz, COMPARE %#lx <- %#lx\n",
@@ -559,8 +1044,8 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
/* If we are writing to COMPARE */
/* Clear pending timer interrupt, if any */
kvm_mips_callbacks->dequeue_timer_int(vcpu);
- kvm_write_c0_guest_compare(cop0,
- vcpu->arch.gprs[rt]);
+ kvm_mips_write_compare(vcpu,
+ vcpu->arch.gprs[rt]);
} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
kvm_write_c0_guest_status(cop0,
vcpu->arch.gprs[rt]);
@@ -571,6 +1056,20 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
#ifdef CONFIG_KVM_MIPS_DYN_TRANS
kvm_mips_trans_mtc0(inst, opc, vcpu);
#endif
+ } else if ((rd == MIPS_CP0_CAUSE) && (sel == 0)) {
+ uint32_t old_cause, new_cause;
+ old_cause = kvm_read_c0_guest_cause(cop0);
+ new_cause = vcpu->arch.gprs[rt];
+ /* Update R/W bits */
+ kvm_change_c0_guest_cause(cop0, 0x08800300,
+ new_cause);
+ /* DC bit enabling/disabling timer? */
+ if ((old_cause ^ new_cause) & CAUSEF_DC) {
+ if (new_cause & CAUSEF_DC)
+ kvm_mips_count_disable_cause(vcpu);
+ else
+ kvm_mips_count_enable_cause(vcpu);
+ }
} else {
cop0->reg[rd][sel] = vcpu->arch.gprs[rt];
#ifdef CONFIG_KVM_MIPS_DYN_TRANS
@@ -894,7 +1393,7 @@ int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
printk("%s: va: %#lx, unmapped: %#x\n", __func__, va, CKSEG0ADDR(pa));
- mips32_SyncICache(CKSEG0ADDR(pa), 32);
+ local_flush_icache_range(CKSEG0ADDR(pa), 32);
return 0;
}
@@ -1332,8 +1831,12 @@ kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
struct kvm_run *run, struct kvm_vcpu *vcpu)
{
enum emulation_result er = EMULATE_DONE;
-
#ifdef DEBUG
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
+ (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+ int index;
+
/*
* If address not in the guest TLB, then we are in trouble
*/
@@ -1542,8 +2045,15 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
}
if ((inst & OPCODE) == SPEC3 && (inst & FUNC) == RDHWR) {
+ int usermode = !KVM_GUEST_KERNEL_MODE(vcpu);
int rd = (inst & RD) >> 11;
int rt = (inst & RT) >> 16;
+ /* If usermode, check RDHWR rd is allowed by guest HWREna */
+ if (usermode && !(kvm_read_c0_guest_hwrena(cop0) & BIT(rd))) {
+ kvm_debug("RDHWR %#x disallowed by HWREna @ %p\n",
+ rd, opc);
+ goto emulate_ri;
+ }
switch (rd) {
case 0: /* CPU number */
arch->gprs[rt] = 0;
@@ -1553,8 +2063,7 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
current_cpu_data.icache.linesz);
break;
case 2: /* Read count register */
- printk("RDHWR: Cont register\n");
- arch->gprs[rt] = kvm_read_c0_guest_count(cop0);
+ arch->gprs[rt] = kvm_mips_read_count(vcpu);
break;
case 3: /* Count register resolution */
switch (current_cpu_data.cputype) {
@@ -1567,31 +2076,27 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
}
break;
case 29:
-#if 1
arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0);
-#else
- /* UserLocal not implemented */
- er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
-#endif
break;
default:
- printk("RDHWR not supported\n");
- er = EMULATE_FAIL;
- break;
+ kvm_debug("RDHWR %#x not supported @ %p\n", rd, opc);
+ goto emulate_ri;
}
} else {
- printk("Emulate RI not supported @ %p: %#x\n", opc, inst);
- er = EMULATE_FAIL;
+ kvm_debug("Emulate RI not supported @ %p: %#x\n", opc, inst);
+ goto emulate_ri;
}
+ return EMULATE_DONE;
+
+emulate_ri:
/*
- * Rollback PC only if emulation was unsuccessful
+ * Rollback PC (if in branch delay slot then the PC already points to
+ * branch target), and pass the RI exception to the guest OS.
*/
- if (er == EMULATE_FAIL) {
- vcpu->arch.pc = curr_pc;
- }
- return er;
+ vcpu->arch.pc = curr_pc;
+ return kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
}
enum emulation_result
@@ -1814,11 +2319,9 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
er = EMULATE_FAIL;
}
} else {
-#ifdef DEBUG
kvm_debug
("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",
tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1);
-#endif
/* OK we have a Guest TLB entry, now inject it into the shadow host TLB */
kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL,
NULL);
diff --git a/arch/mips/kvm/kvm_tlb.c b/arch/mips/kvm/kvm_tlb.c
index c777dd36d4a..8a5a700ad8d 100644
--- a/arch/mips/kvm/kvm_tlb.c
+++ b/arch/mips/kvm/kvm_tlb.c
@@ -10,7 +10,6 @@
* Authors: Sanjay Lal <sanjayl@kymasys.com>
*/
-#include <linux/init.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/mm.h>
@@ -25,6 +24,7 @@
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
+#include <asm/tlb.h>
#undef CONFIG_MIPS_MT
#include <asm/r4kcache.h>
@@ -35,9 +35,6 @@
#define PRIx64 "llx"
-/* Use VZ EntryHi.EHINV to invalidate TLB entries */
-#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
-
atomic_t kvm_mips_instance;
EXPORT_SYMBOL(kvm_mips_instance);
@@ -147,30 +144,6 @@ void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
}
}
-void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu)
-{
- int i;
- volatile struct kvm_mips_tlb tlb;
-
- printk("Shadow TLBs:\n");
- for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
- tlb = vcpu->arch.shadow_tlb[smp_processor_id()][i];
- printk("TLB%c%3d Hi 0x%08lx ",
- (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
- i, tlb.tlb_hi);
- printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
- (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
- (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
- (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
- (tlb.tlb_lo0 >> 3) & 7);
- printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
- (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
- (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
- (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
- (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
- }
-}
-
static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
{
int srcu_idx, err = 0;
@@ -249,26 +222,19 @@ kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
return -1;
}
- if (idx < 0) {
- idx = read_c0_random() % current_cpu_data.tlbsize;
- write_c0_index(idx);
- mtc0_tlbw_hazard();
- }
write_c0_entrylo0(entrylo0);
write_c0_entrylo1(entrylo1);
mtc0_tlbw_hazard();
- tlb_write_indexed();
+ if (idx < 0)
+ tlb_write_random();
+ else
+ tlb_write_indexed();
tlbw_use_hazard();
-#ifdef DEBUG
- if (debug) {
- kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] "
- "entrylo0(R): 0x%08lx, entrylo1(R): 0x%08lx\n",
- vcpu->arch.pc, idx, read_c0_entryhi(),
- read_c0_entrylo0(), read_c0_entrylo1());
- }
-#endif
+ kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0(R): 0x%08lx, entrylo1(R): 0x%08lx\n",
+ vcpu->arch.pc, idx, read_c0_entryhi(),
+ read_c0_entrylo0(), read_c0_entrylo1());
/* Flush D-cache */
if (flush_dcache_mask) {
@@ -375,11 +341,9 @@ int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
mtc0_tlbw_hazard();
tlbw_use_hazard();
-#ifdef DEBUG
kvm_debug ("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n",
vcpu->arch.pc, read_c0_index(), read_c0_entryhi(),
read_c0_entrylo0(), read_c0_entrylo1());
-#endif
/* Restore old ASID */
write_c0_entryhi(old_entryhi);
@@ -427,10 +391,8 @@ kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
(tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
-#ifdef DEBUG
kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
tlb->tlb_lo0, tlb->tlb_lo1);
-#endif
return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
tlb->tlb_mask);
@@ -451,10 +413,8 @@ int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
}
}
-#ifdef DEBUG
kvm_debug("%s: entryhi: %#lx, index: %d lo0: %#lx, lo1: %#lx\n",
__func__, entryhi, index, tlb[i].tlb_lo0, tlb[i].tlb_lo1);
-#endif
return index;
}
@@ -488,9 +448,7 @@ int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
local_irq_restore(flags);
-#ifdef DEBUG
kvm_debug("Host TLB lookup, %#lx, idx: %2d\n", vaddr, idx);
-#endif
return idx;
}
@@ -535,12 +493,9 @@ int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
local_irq_restore(flags);
-#ifdef DEBUG
- if (idx > 0) {
+ if (idx > 0)
kvm_debug("%s: Invalidated entryhi %#lx @ idx %d\n", __func__,
- (va & VPN2_MASK) | (vcpu->arch.asid_map[va & ASID_MASK] & ASID_MASK), idx);
- }
-#endif
+ (va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu), idx);
return 0;
}
@@ -657,70 +612,6 @@ kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
}
-void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu)
-{
- unsigned long flags;
- unsigned long old_entryhi;
- unsigned long old_pagemask;
- int entry = 0;
- int cpu = smp_processor_id();
-
- local_irq_save(flags);
-
- old_entryhi = read_c0_entryhi();
- old_pagemask = read_c0_pagemask();
-
- for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
- write_c0_index(entry);
- mtc0_tlbw_hazard();
- tlb_read();
- tlbw_use_hazard();
-
- vcpu->arch.shadow_tlb[cpu][entry].tlb_hi = read_c0_entryhi();
- vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = read_c0_entrylo0();
- vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = read_c0_entrylo1();
- vcpu->arch.shadow_tlb[cpu][entry].tlb_mask = read_c0_pagemask();
- }
-
- write_c0_entryhi(old_entryhi);
- write_c0_pagemask(old_pagemask);
- mtc0_tlbw_hazard();
-
- local_irq_restore(flags);
-
-}
-
-void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu)
-{
- unsigned long flags;
- unsigned long old_ctx;
- int entry;
- int cpu = smp_processor_id();
-
- local_irq_save(flags);
-
- old_ctx = read_c0_entryhi();
-
- for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
- write_c0_entryhi(vcpu->arch.shadow_tlb[cpu][entry].tlb_hi);
- mtc0_tlbw_hazard();
- write_c0_entrylo0(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0);
- write_c0_entrylo1(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1);
-
- write_c0_index(entry);
- mtc0_tlbw_hazard();
-
- tlb_write_indexed();
- tlbw_use_hazard();
- }
-
- tlbw_use_hazard();
- write_c0_entryhi(old_ctx);
- mtc0_tlbw_hazard();
- local_irq_restore(flags);
-}
-
-
void kvm_local_flush_tlb_all(void)
{
unsigned long flags;
@@ -749,28 +640,21 @@ void kvm_local_flush_tlb_all(void)
local_irq_restore(flags);
}
-void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu)
+/**
+ * kvm_mips_migrate_count() - Migrate timer.
+ * @vcpu: Virtual CPU.
+ *
+ * Migrate CP0_Count hrtimer to the current CPU by cancelling and restarting it
+ * if it was running prior to being cancelled.
+ *
+ * Must be called when the VCPU is migrated to a different CPU to ensure that
+ * timer expiry during guest execution interrupts the guest and causes the
+ * interrupt to be delivered in a timely manner.
+ */
+static void kvm_mips_migrate_count(struct kvm_vcpu *vcpu)
{
- int cpu, entry;
-
- for_each_possible_cpu(cpu) {
- for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
- vcpu->arch.shadow_tlb[cpu][entry].tlb_hi =
- UNIQUE_ENTRYHI(entry);
- vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = 0x0;
- vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = 0x0;
- vcpu->arch.shadow_tlb[cpu][entry].tlb_mask =
- read_c0_pagemask();
-#ifdef DEBUG
- kvm_debug
- ("shadow_tlb[%d][%d]: tlb_hi: %#lx, lo0: %#lx, lo1: %#lx\n",
- cpu, entry,
- vcpu->arch.shadow_tlb[cpu][entry].tlb_hi,
- vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0,
- vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1);
-#endif
- }
- }
+ if (hrtimer_cancel(&vcpu->arch.comparecount_timer))
+ hrtimer_restart(&vcpu->arch.comparecount_timer);
}
/* Restore ASID once we are scheduled back after preemption */
@@ -779,9 +663,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
unsigned long flags;
int newasid = 0;
-#ifdef DEBUG
kvm_debug("%s: vcpu %p, cpu: %d\n", __func__, vcpu, cpu);
-#endif
/* Alocate new kernel and user ASIDs if needed */
@@ -797,26 +679,24 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vcpu->arch.guest_user_mm.context.asid[cpu];
newasid++;
- kvm_info("[%d]: cpu_context: %#lx\n", cpu,
- cpu_context(cpu, current->mm));
- kvm_info("[%d]: Allocated new ASID for Guest Kernel: %#x\n",
- cpu, vcpu->arch.guest_kernel_asid[cpu]);
- kvm_info("[%d]: Allocated new ASID for Guest User: %#x\n", cpu,
- vcpu->arch.guest_user_asid[cpu]);
+ kvm_debug("[%d]: cpu_context: %#lx\n", cpu,
+ cpu_context(cpu, current->mm));
+ kvm_debug("[%d]: Allocated new ASID for Guest Kernel: %#x\n",
+ cpu, vcpu->arch.guest_kernel_asid[cpu]);
+ kvm_debug("[%d]: Allocated new ASID for Guest User: %#x\n", cpu,
+ vcpu->arch.guest_user_asid[cpu]);
}
if (vcpu->arch.last_sched_cpu != cpu) {
- kvm_info("[%d->%d]KVM VCPU[%d] switch\n",
- vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id);
- }
-
- /* Only reload shadow host TLB if new ASIDs haven't been allocated */
-#if 0
- if ((atomic_read(&kvm_mips_instance) > 1) && !newasid) {
- kvm_mips_flush_host_tlb(0);
- kvm_shadow_tlb_load(vcpu);
+ kvm_debug("[%d->%d]KVM VCPU[%d] switch\n",
+ vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id);
+ /*
+ * Migrate the timer interrupt to the current CPU so that it
+ * always interrupts the guest and synchronously triggers a
+ * guest timer interrupt.
+ */
+ kvm_mips_migrate_count(vcpu);
}
-#endif
if (!newasid) {
/* If we preempted while the guest was executing, then reload the pre-empted ASID */
@@ -863,12 +743,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
vcpu->arch.preempt_entryhi = read_c0_entryhi();
vcpu->arch.last_sched_cpu = cpu;
-#if 0
- if ((atomic_read(&kvm_mips_instance) > 1)) {
- kvm_shadow_tlb_put(vcpu);
- }
-#endif
-
if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) &
ASID_VERSION_MASK)) {
kvm_debug("%s: Dropping MMU Context: %#lx\n", __func__,
@@ -930,10 +804,8 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL(kvm_local_flush_tlb_all);
-EXPORT_SYMBOL(kvm_shadow_tlb_put);
EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault);
EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault);
-EXPORT_SYMBOL(kvm_mips_init_shadow_tlb);
EXPORT_SYMBOL(kvm_mips_dump_host_tlbs);
EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault);
EXPORT_SYMBOL(kvm_mips_host_tlb_lookup);
@@ -941,8 +813,6 @@ EXPORT_SYMBOL(kvm_mips_flush_host_tlb);
EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup);
EXPORT_SYMBOL(kvm_mips_host_tlb_inv);
EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa);
-EXPORT_SYMBOL(kvm_shadow_tlb_load);
-EXPORT_SYMBOL(kvm_mips_dump_shadow_tlbs);
EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs);
EXPORT_SYMBOL(kvm_get_inst);
EXPORT_SYMBOL(kvm_arch_vcpu_load);
diff --git a/arch/mips/kvm/kvm_trap_emul.c b/arch/mips/kvm/kvm_trap_emul.c
index 30d725321db..693f952b2fb 100644
--- a/arch/mips/kvm/kvm_trap_emul.c
+++ b/arch/mips/kvm/kvm_trap_emul.c
@@ -32,9 +32,7 @@ static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
gpa = KVM_INVALID_ADDR;
}
-#ifdef DEBUG
kvm_debug("%s: gva %#lx, gpa: %#llx\n", __func__, gva, gpa);
-#endif
return gpa;
}
@@ -85,11 +83,9 @@ static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu)
if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
|| KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
-#ifdef DEBUG
kvm_debug
("USER/KSEG23 ADDR TLB MOD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
cause, opc, badvaddr);
-#endif
er = kvm_mips_handle_tlbmod(cause, opc, run, vcpu);
if (er == EMULATE_DONE)
@@ -138,11 +134,9 @@ static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu)
}
} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
|| KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
-#ifdef DEBUG
kvm_debug
("USER ADDR TLB LD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
cause, opc, badvaddr);
-#endif
er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
if (er == EMULATE_DONE)
ret = RESUME_GUEST;
@@ -188,10 +182,8 @@ static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu)
}
} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
|| KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
-#ifdef DEBUG
kvm_debug("USER ADDR TLB ST fault: PC: %#lx, BadVaddr: %#lx\n",
vcpu->arch.pc, badvaddr);
-#endif
/* User Address (UA) fault, this could happen if
* (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
@@ -236,9 +228,7 @@ static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu)
if (KVM_GUEST_KERNEL_MODE(vcpu)
&& (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1)) {
-#ifdef DEBUG
kvm_debug("Emulate Store to MMIO space\n");
-#endif
er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
if (er == EMULATE_FAIL) {
printk("Emulate Store to MMIO space failed\n");
@@ -268,9 +258,7 @@ static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu)
int ret = RESUME_GUEST;
if (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1) {
-#ifdef DEBUG
kvm_debug("Emulate Load from MMIO space @ %#lx\n", badvaddr);
-#endif
er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
if (er == EMULATE_FAIL) {
printk("Emulate Load from MMIO space failed\n");
@@ -401,6 +389,78 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
return 0;
}
+static int kvm_trap_emul_get_one_reg(struct kvm_vcpu *vcpu,
+ const struct kvm_one_reg *reg,
+ s64 *v)
+{
+ switch (reg->id) {
+ case KVM_REG_MIPS_CP0_COUNT:
+ *v = kvm_mips_read_count(vcpu);
+ break;
+ case KVM_REG_MIPS_COUNT_CTL:
+ *v = vcpu->arch.count_ctl;
+ break;
+ case KVM_REG_MIPS_COUNT_RESUME:
+ *v = ktime_to_ns(vcpu->arch.count_resume);
+ break;
+ case KVM_REG_MIPS_COUNT_HZ:
+ *v = vcpu->arch.count_hz;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
+ const struct kvm_one_reg *reg,
+ s64 v)
+{
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ int ret = 0;
+
+ switch (reg->id) {
+ case KVM_REG_MIPS_CP0_COUNT:
+ kvm_mips_write_count(vcpu, v);
+ break;
+ case KVM_REG_MIPS_CP0_COMPARE:
+ kvm_mips_write_compare(vcpu, v);
+ break;
+ case KVM_REG_MIPS_CP0_CAUSE:
+ /*
+ * If the timer is stopped or started (DC bit) it must look
+ * atomic with changes to the interrupt pending bits (TI, IRQ5).
+ * A timer interrupt should not happen in between.
+ */
+ if ((kvm_read_c0_guest_cause(cop0) ^ v) & CAUSEF_DC) {
+ if (v & CAUSEF_DC) {
+ /* disable timer first */
+ kvm_mips_count_disable_cause(vcpu);
+ kvm_change_c0_guest_cause(cop0, ~CAUSEF_DC, v);
+ } else {
+ /* enable timer last */
+ kvm_change_c0_guest_cause(cop0, ~CAUSEF_DC, v);
+ kvm_mips_count_enable_cause(vcpu);
+ }
+ } else {
+ kvm_write_c0_guest_cause(cop0, v);
+ }
+ break;
+ case KVM_REG_MIPS_COUNT_CTL:
+ ret = kvm_mips_set_count_ctl(vcpu, v);
+ break;
+ case KVM_REG_MIPS_COUNT_RESUME:
+ ret = kvm_mips_set_count_resume(vcpu, v);
+ break;
+ case KVM_REG_MIPS_COUNT_HZ:
+ ret = kvm_mips_set_count_hz(vcpu, v);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
/* exit handlers */
.handle_cop_unusable = kvm_trap_emul_handle_cop_unusable,
@@ -423,6 +483,8 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
.dequeue_io_int = kvm_mips_dequeue_io_int_cb,
.irq_deliver = kvm_mips_irq_deliver_cb,
.irq_clear = kvm_mips_irq_clear_cb,
+ .get_one_reg = kvm_trap_emul_get_one_reg,
+ .set_one_reg = kvm_trap_emul_set_one_reg,
};
int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)
diff --git a/arch/mips/lantiq/dts/easy50712.dts b/arch/mips/lantiq/dts/easy50712.dts
index fac1f5b178e..143b8a37b5e 100644
--- a/arch/mips/lantiq/dts/easy50712.dts
+++ b/arch/mips/lantiq/dts/easy50712.dts
@@ -8,6 +8,7 @@
};
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index eb3e1865963..030568a70ac 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -61,7 +61,7 @@
/* we have a cascade of 8 irqs */
#define MIPS_CPU_IRQ_CASCADE 8
-#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
+#ifdef CONFIG_MIPS_MT_SMP
int gic_present;
#endif
@@ -390,7 +390,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
ret = of_irq_to_resource_table(eiu_node,
ltq_eiu_irq, exin_avail);
if (ret != exin_avail)
- panic("failed to load external irq resources\n");
+ panic("failed to load external irq resources");
if (request_mem_region(res.start, resource_size(&res),
res.name) < 0)
@@ -440,7 +440,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call);
#endif
-#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
+#ifndef CONFIG_MIPS_MT_SMP
set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
#else
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 49c46037028..7447d322d14 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -14,6 +14,7 @@
#include <asm/bootinfo.h>
#include <asm/time.h>
+#include <asm/prom.h>
#include <lantiq.h>
@@ -70,23 +71,12 @@ void __init plat_mem_setup(void)
* Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing
*/
- __dt_setup_arch(&__dtb_start);
+ __dt_setup_arch(__dtb_start);
}
void __init device_tree_init(void)
{
- unsigned long base, size;
-
- if (!initial_boot_params)
- return;
-
- base = virt_to_phys((void *)initial_boot_params);
- size = be32_to_cpu(initial_boot_params->totalsize);
-
- /* Before we do anything, lets reserve the dt blob */
- reserve_bootmem(base, size, BOOTMEM_DEFAULT);
-
- unflatten_device_tree();
+ unflatten_and_copy_device_tree();
}
void __init prom_init(void)
diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
index 8e07b5f28ef..bfd2d58c1d6 100644
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -26,6 +26,4 @@ struct ltq_soc_info {
extern void ltq_soc_detect(struct ltq_soc_info *i);
extern void ltq_soc_init(void);
-extern struct boot_param_header __dtb_start;
-
#endif
diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
index 1ab576dc9bd..8750dc0a1bf 100644
--- a/arch/mips/lantiq/xway/clk.c
+++ b/arch/mips/lantiq/xway/clk.c
@@ -8,7 +8,6 @@
#include <linux/io.h>
#include <linux/export.h>
-#include <linux/init.h>
#include <linux/clk.h>
#include <asm/time.h>
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 08f7ebd9c77..78a91fa4194 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -220,10 +220,6 @@ ltq_dma_init(struct platform_device *pdev)
int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- panic("Failed to get dma resource");
-
- /* remap dma register range */
ltq_dma_membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ltq_dma_membase))
panic("Failed to remap dma resource");
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index c24924fe087..51804b10a03 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -128,7 +128,7 @@ static int pmu_enable(struct clk *clk)
do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
if (!retry)
- panic("activating PMU module failed!\n");
+ panic("activating PMU module failed!");
return 0;
}
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c
index 793e234719a..942f32b91d1 100644
--- a/arch/mips/lasat/at93c.c
+++ b/arch/mips/lasat/at93c.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <asm/lasat/lasat.h>
#include <linux/module.h>
-#include <linux/init.h>
#include "at93c.h"
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c
index 7eb33489269..d613b97cd51 100644
--- a/arch/mips/lasat/picvue.c
+++ b/arch/mips/lasat/picvue.c
@@ -9,7 +9,6 @@
#include <asm/bootinfo.h>
#include <asm/lasat/lasat.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/string.h>
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
index 638c5db122c..2bcd8391bc9 100644
--- a/arch/mips/lasat/picvue_proc.c
+++ b/arch/mips/lasat/picvue_proc.c
@@ -175,7 +175,7 @@ static void pvc_proc_cleanup(void)
remove_proc_entry("scroll", pvc_display_dir);
remove_proc_entry(DISPLAY_DIR_NAME, NULL);
- del_timer(&timer);
+ del_timer_sync(&timer);
}
static int __init pvc_proc_init(void)
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index a6adffbb4e5..9901237563c 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -8,6 +8,7 @@
* Copyright (C) 1998, 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) 2007 Maciej W. Rozycki
+ * Copyright (C) 2014 Imagination Technologies Ltd.
*/
#include <linux/errno.h>
#include <asm/asm.h>
@@ -55,14 +56,20 @@
#define UNIT(unit) ((unit)*NBYTES)
#define ADDC(sum,reg) \
+ .set push; \
+ .set noat; \
ADD sum, reg; \
sltu v1, sum, reg; \
ADD sum, v1; \
+ .set pop
#define ADDC32(sum,reg) \
+ .set push; \
+ .set noat; \
addu sum, reg; \
sltu v1, sum, reg; \
addu sum, v1; \
+ .set pop
#define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \
LOAD _t0, (offset + UNIT(0))(src); \
@@ -296,7 +303,7 @@ LEAF(csum_partial)
* checksum and copy routines based on memcpy.S
*
* csum_partial_copy_nocheck(src, dst, len, sum)
- * __csum_partial_copy_user(src, dst, len, sum, errp)
+ * __csum_partial_copy_kernel(src, dst, len, sum, errp)
*
* See "Spec" in memcpy.S for details. Unlike __copy_user, all
* function in this file use the standard calling convention.
@@ -327,20 +334,58 @@ LEAF(csum_partial)
* These handlers do not need to overwrite any data.
*/
-#define EXC(inst_reg,addr,handler) \
-9: inst_reg, addr; \
- .section __ex_table,"a"; \
- PTR 9b, handler; \
- .previous
+/* Instruction type */
+#define LD_INSN 1
+#define ST_INSN 2
+#define LEGACY_MODE 1
+#define EVA_MODE 2
+#define USEROP 1
+#define KERNELOP 2
+
+/*
+ * Wrapper to add an entry in the exception table
+ * in case the insn causes a memory exception.
+ * Arguments:
+ * insn : Load/store instruction
+ * type : Instruction type
+ * reg : Register
+ * addr : Address
+ * handler : Exception handler
+ */
+#define EXC(insn, type, reg, addr, handler) \
+ .if \mode == LEGACY_MODE; \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous; \
+ /* This is enabled in EVA mode */ \
+ .else; \
+ /* If loading from user or storing to user */ \
+ .if ((\from == USEROP) && (type == LD_INSN)) || \
+ ((\to == USEROP) && (type == ST_INSN)); \
+9: __BUILD_EVA_INSN(insn##e, reg, addr); \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous; \
+ .else; \
+ /* EVA without exception */ \
+ insn reg, addr; \
+ .endif; \
+ .endif
+
+#undef LOAD
#ifdef USE_DOUBLE
-#define LOAD ld
-#define LOADL ldl
-#define LOADR ldr
-#define STOREL sdl
-#define STORER sdr
-#define STORE sd
+#define LOADK ld /* No exception */
+#define LOAD(reg, addr, handler) EXC(ld, LD_INSN, reg, addr, handler)
+#define LOADBU(reg, addr, handler) EXC(lbu, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler) EXC(ldl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler) EXC(ldr, LD_INSN, reg, addr, handler)
+#define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler) EXC(sdl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler) EXC(sdr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler) EXC(sd, ST_INSN, reg, addr, handler)
#define ADD daddu
#define SUB dsubu
#define SRL dsrl
@@ -352,12 +397,15 @@ LEAF(csum_partial)
#else
-#define LOAD lw
-#define LOADL lwl
-#define LOADR lwr
-#define STOREL swl
-#define STORER swr
-#define STORE sw
+#define LOADK lw /* No exception */
+#define LOAD(reg, addr, handler) EXC(lw, LD_INSN, reg, addr, handler)
+#define LOADBU(reg, addr, handler) EXC(lbu, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler) EXC(lwl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler) EXC(lwr, LD_INSN, reg, addr, handler)
+#define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler) EXC(swl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler) EXC(swr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler) EXC(sw, ST_INSN, reg, addr, handler)
#define ADD addu
#define SUB subu
#define SRL srl
@@ -396,14 +444,20 @@ LEAF(csum_partial)
.set at=v1
#endif
-LEAF(__csum_partial_copy_user)
+ .macro __BUILD_CSUM_PARTIAL_COPY_USER mode, from, to, __nocheck
+
PTR_ADDU AT, src, len /* See (1) above. */
+ /* initialize __nocheck if this the first time we execute this
+ * macro
+ */
#ifdef CONFIG_64BIT
move errptr, a4
#else
lw errptr, 16(sp)
#endif
-FEXPORT(csum_partial_copy_nocheck)
+ .if \__nocheck == 1
+ FEXPORT(csum_partial_copy_nocheck)
+ .endif
move sum, zero
move odd, zero
/*
@@ -419,48 +473,48 @@ FEXPORT(csum_partial_copy_nocheck)
*/
sltu t2, len, NBYTES
and t1, dst, ADDRMASK
- bnez t2, .Lcopy_bytes_checklen
+ bnez t2, .Lcopy_bytes_checklen\@
and t0, src, ADDRMASK
andi odd, dst, 0x1 /* odd buffer? */
- bnez t1, .Ldst_unaligned
+ bnez t1, .Ldst_unaligned\@
nop
- bnez t0, .Lsrc_unaligned_dst_aligned
+ bnez t0, .Lsrc_unaligned_dst_aligned\@
/*
* use delay slot for fall-through
* src and dst are aligned; need to compute rem
*/
-.Lboth_aligned:
+.Lboth_aligned\@:
SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter
- beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES
+ beqz t0, .Lcleanup_both_aligned\@ # len < 8*NBYTES
nop
SUB len, 8*NBYTES # subtract here for bgez loop
.align 4
1:
-EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
-EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
-EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
-EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
-EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy)
-EXC( LOAD t5, UNIT(5)(src), .Ll_exc_copy)
-EXC( LOAD t6, UNIT(6)(src), .Ll_exc_copy)
-EXC( LOAD t7, UNIT(7)(src), .Ll_exc_copy)
+ LOAD(t0, UNIT(0)(src), .Ll_exc\@)
+ LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@)
+ LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@)
+ LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@)
+ LOAD(t4, UNIT(4)(src), .Ll_exc_copy\@)
+ LOAD(t5, UNIT(5)(src), .Ll_exc_copy\@)
+ LOAD(t6, UNIT(6)(src), .Ll_exc_copy\@)
+ LOAD(t7, UNIT(7)(src), .Ll_exc_copy\@)
SUB len, len, 8*NBYTES
ADD src, src, 8*NBYTES
-EXC( STORE t0, UNIT(0)(dst), .Ls_exc)
+ STORE(t0, UNIT(0)(dst), .Ls_exc\@)
ADDC(sum, t0)
-EXC( STORE t1, UNIT(1)(dst), .Ls_exc)
+ STORE(t1, UNIT(1)(dst), .Ls_exc\@)
ADDC(sum, t1)
-EXC( STORE t2, UNIT(2)(dst), .Ls_exc)
+ STORE(t2, UNIT(2)(dst), .Ls_exc\@)
ADDC(sum, t2)
-EXC( STORE t3, UNIT(3)(dst), .Ls_exc)
+ STORE(t3, UNIT(3)(dst), .Ls_exc\@)
ADDC(sum, t3)
-EXC( STORE t4, UNIT(4)(dst), .Ls_exc)
+ STORE(t4, UNIT(4)(dst), .Ls_exc\@)
ADDC(sum, t4)
-EXC( STORE t5, UNIT(5)(dst), .Ls_exc)
+ STORE(t5, UNIT(5)(dst), .Ls_exc\@)
ADDC(sum, t5)
-EXC( STORE t6, UNIT(6)(dst), .Ls_exc)
+ STORE(t6, UNIT(6)(dst), .Ls_exc\@)
ADDC(sum, t6)
-EXC( STORE t7, UNIT(7)(dst), .Ls_exc)
+ STORE(t7, UNIT(7)(dst), .Ls_exc\@)
ADDC(sum, t7)
.set reorder /* DADDI_WAR */
ADD dst, dst, 8*NBYTES
@@ -471,44 +525,44 @@ EXC( STORE t7, UNIT(7)(dst), .Ls_exc)
/*
* len == the number of bytes left to copy < 8*NBYTES
*/
-.Lcleanup_both_aligned:
+.Lcleanup_both_aligned\@:
#define rem t7
- beqz len, .Ldone
+ beqz len, .Ldone\@
sltu t0, len, 4*NBYTES
- bnez t0, .Lless_than_4units
+ bnez t0, .Lless_than_4units\@
and rem, len, (NBYTES-1) # rem = len % NBYTES
/*
* len >= 4*NBYTES
*/
-EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
-EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
-EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
-EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
+ LOAD(t0, UNIT(0)(src), .Ll_exc\@)
+ LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@)
+ LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@)
+ LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@)
SUB len, len, 4*NBYTES
ADD src, src, 4*NBYTES
-EXC( STORE t0, UNIT(0)(dst), .Ls_exc)
+ STORE(t0, UNIT(0)(dst), .Ls_exc\@)
ADDC(sum, t0)
-EXC( STORE t1, UNIT(1)(dst), .Ls_exc)
+ STORE(t1, UNIT(1)(dst), .Ls_exc\@)
ADDC(sum, t1)
-EXC( STORE t2, UNIT(2)(dst), .Ls_exc)
+ STORE(t2, UNIT(2)(dst), .Ls_exc\@)
ADDC(sum, t2)
-EXC( STORE t3, UNIT(3)(dst), .Ls_exc)
+ STORE(t3, UNIT(3)(dst), .Ls_exc\@)
ADDC(sum, t3)
.set reorder /* DADDI_WAR */
ADD dst, dst, 4*NBYTES
- beqz len, .Ldone
+ beqz len, .Ldone\@
.set noreorder
-.Lless_than_4units:
+.Lless_than_4units\@:
/*
* rem = len % NBYTES
*/
- beq rem, len, .Lcopy_bytes
+ beq rem, len, .Lcopy_bytes\@
nop
1:
-EXC( LOAD t0, 0(src), .Ll_exc)
+ LOAD(t0, 0(src), .Ll_exc\@)
ADD src, src, NBYTES
SUB len, len, NBYTES
-EXC( STORE t0, 0(dst), .Ls_exc)
+ STORE(t0, 0(dst), .Ls_exc\@)
ADDC(sum, t0)
.set reorder /* DADDI_WAR */
ADD dst, dst, NBYTES
@@ -527,20 +581,20 @@ EXC( STORE t0, 0(dst), .Ls_exc)
* more instruction-level parallelism.
*/
#define bits t2
- beqz len, .Ldone
+ beqz len, .Ldone\@
ADD t1, dst, len # t1 is just past last byte of dst
li bits, 8*NBYTES
SLL rem, len, 3 # rem = number of bits to keep
-EXC( LOAD t0, 0(src), .Ll_exc)
+ LOAD(t0, 0(src), .Ll_exc\@)
SUB bits, bits, rem # bits = number of bits to discard
SHIFT_DISCARD t0, t0, bits
-EXC( STREST t0, -1(t1), .Ls_exc)
+ STREST(t0, -1(t1), .Ls_exc\@)
SHIFT_DISCARD_REVERT t0, t0, bits
.set reorder
ADDC(sum, t0)
- b .Ldone
+ b .Ldone\@
.set noreorder
-.Ldst_unaligned:
+.Ldst_unaligned\@:
/*
* dst is unaligned
* t0 = src & ADDRMASK
@@ -551,25 +605,25 @@ EXC( STREST t0, -1(t1), .Ls_exc)
* Set match = (src and dst have same alignment)
*/
#define match rem
-EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc)
+ LDFIRST(t3, FIRST(0)(src), .Ll_exc\@)
ADD t2, zero, NBYTES
-EXC( LDREST t3, REST(0)(src), .Ll_exc_copy)
+ LDREST(t3, REST(0)(src), .Ll_exc_copy\@)
SUB t2, t2, t1 # t2 = number of bytes copied
xor match, t0, t1
-EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc)
+ STFIRST(t3, FIRST(0)(dst), .Ls_exc\@)
SLL t4, t1, 3 # t4 = number of bits to discard
SHIFT_DISCARD t3, t3, t4
/* no SHIFT_DISCARD_REVERT to handle odd buffer properly */
ADDC(sum, t3)
- beq len, t2, .Ldone
+ beq len, t2, .Ldone\@
SUB len, len, t2
ADD dst, dst, t2
- beqz match, .Lboth_aligned
+ beqz match, .Lboth_aligned\@
ADD src, src, t2
-.Lsrc_unaligned_dst_aligned:
+.Lsrc_unaligned_dst_aligned\@:
SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
- beqz t0, .Lcleanup_src_unaligned
+ beqz t0, .Lcleanup_src_unaligned\@
and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
1:
/*
@@ -578,53 +632,53 @@ EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc)
* It's OK to load FIRST(N+1) before REST(N) because the two addresses
* are to the same unit (unless src is aligned, but it's not).
*/
-EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
-EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy)
+ LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+ LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy\@)
SUB len, len, 4*NBYTES
-EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
-EXC( LDREST t1, REST(1)(src), .Ll_exc_copy)
-EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy)
-EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy)
-EXC( LDREST t2, REST(2)(src), .Ll_exc_copy)
-EXC( LDREST t3, REST(3)(src), .Ll_exc_copy)
+ LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
+ LDREST(t1, REST(1)(src), .Ll_exc_copy\@)
+ LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy\@)
+ LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy\@)
+ LDREST(t2, REST(2)(src), .Ll_exc_copy\@)
+ LDREST(t3, REST(3)(src), .Ll_exc_copy\@)
ADD src, src, 4*NBYTES
#ifdef CONFIG_CPU_SB1
nop # improves slotting
#endif
-EXC( STORE t0, UNIT(0)(dst), .Ls_exc)
+ STORE(t0, UNIT(0)(dst), .Ls_exc\@)
ADDC(sum, t0)
-EXC( STORE t1, UNIT(1)(dst), .Ls_exc)
+ STORE(t1, UNIT(1)(dst), .Ls_exc\@)
ADDC(sum, t1)
-EXC( STORE t2, UNIT(2)(dst), .Ls_exc)
+ STORE(t2, UNIT(2)(dst), .Ls_exc\@)
ADDC(sum, t2)
-EXC( STORE t3, UNIT(3)(dst), .Ls_exc)
+ STORE(t3, UNIT(3)(dst), .Ls_exc\@)
ADDC(sum, t3)
.set reorder /* DADDI_WAR */
ADD dst, dst, 4*NBYTES
bne len, rem, 1b
.set noreorder
-.Lcleanup_src_unaligned:
- beqz len, .Ldone
+.Lcleanup_src_unaligned\@:
+ beqz len, .Ldone\@
and rem, len, NBYTES-1 # rem = len % NBYTES
- beq rem, len, .Lcopy_bytes
+ beq rem, len, .Lcopy_bytes\@
nop
1:
-EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
-EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
+ LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+ LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
ADD src, src, NBYTES
SUB len, len, NBYTES
-EXC( STORE t0, 0(dst), .Ls_exc)
+ STORE(t0, 0(dst), .Ls_exc\@)
ADDC(sum, t0)
.set reorder /* DADDI_WAR */
ADD dst, dst, NBYTES
bne len, rem, 1b
.set noreorder
-.Lcopy_bytes_checklen:
- beqz len, .Ldone
+.Lcopy_bytes_checklen\@:
+ beqz len, .Ldone\@
nop
-.Lcopy_bytes:
+.Lcopy_bytes\@:
/* 0 < len < NBYTES */
#ifdef CONFIG_CPU_LITTLE_ENDIAN
#define SHIFT_START 0
@@ -637,12 +691,12 @@ EXC( STORE t0, 0(dst), .Ls_exc)
li t3, SHIFT_START # shift
/* use .Ll_exc_copy here to return correct sum on fault */
#define COPY_BYTE(N) \
-EXC( lbu t0, N(src), .Ll_exc_copy); \
+ LOADBU(t0, N(src), .Ll_exc_copy\@); \
SUB len, len, 1; \
-EXC( sb t0, N(dst), .Ls_exc); \
+ STOREB(t0, N(dst), .Ls_exc\@); \
SLLV t0, t0, t3; \
addu t3, SHIFT_INC; \
- beqz len, .Lcopy_bytes_done; \
+ beqz len, .Lcopy_bytes_done\@; \
or t2, t0
COPY_BYTE(0)
@@ -653,15 +707,17 @@ EXC( sb t0, N(dst), .Ls_exc); \
COPY_BYTE(4)
COPY_BYTE(5)
#endif
-EXC( lbu t0, NBYTES-2(src), .Ll_exc_copy)
+ LOADBU(t0, NBYTES-2(src), .Ll_exc_copy\@)
SUB len, len, 1
-EXC( sb t0, NBYTES-2(dst), .Ls_exc)
+ STOREB(t0, NBYTES-2(dst), .Ls_exc\@)
SLLV t0, t0, t3
or t2, t0
-.Lcopy_bytes_done:
+.Lcopy_bytes_done\@:
ADDC(sum, t2)
-.Ldone:
+.Ldone\@:
/* fold checksum */
+ .set push
+ .set noat
#ifdef USE_DOUBLE
dsll32 v1, sum, 0
daddu sum, v1
@@ -684,12 +740,13 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc)
or sum, sum, t0
1:
#endif
+ .set pop
.set reorder
ADDC32(sum, psum)
jr ra
.set noreorder
-.Ll_exc_copy:
+.Ll_exc_copy\@:
/*
* Copy bytes from src until faulting load address (or until a
* lb faults)
@@ -700,11 +757,11 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc)
*
* Assumes src < THREAD_BUADDR($28)
*/
- LOAD t0, TI_TASK($28)
+ LOADK t0, TI_TASK($28)
li t2, SHIFT_START
- LOAD t0, THREAD_BUADDR(t0)
+ LOADK t0, THREAD_BUADDR(t0)
1:
-EXC( lbu t1, 0(src), .Ll_exc)
+ LOADBU(t1, 0(src), .Ll_exc\@)
ADD src, src, 1
sb t1, 0(dst) # can't fault -- we're copy_from_user
SLLV t1, t1, t2
@@ -714,10 +771,10 @@ EXC( lbu t1, 0(src), .Ll_exc)
ADD dst, dst, 1
bne src, t0, 1b
.set noreorder
-.Ll_exc:
- LOAD t0, TI_TASK($28)
+.Ll_exc\@:
+ LOADK t0, TI_TASK($28)
nop
- LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
+ LOADK t0, THREAD_BUADDR(t0) # t0 is just past last good address
nop
SUB len, AT, t0 # len number of uncopied bytes
/*
@@ -733,7 +790,7 @@ EXC( lbu t1, 0(src), .Ll_exc)
*/
.set reorder /* DADDI_WAR */
SUB src, len, 1
- beqz len, .Ldone
+ beqz len, .Ldone\@
.set noreorder
1: sb zero, 0(dst)
ADD dst, dst, 1
@@ -748,13 +805,31 @@ EXC( lbu t1, 0(src), .Ll_exc)
SUB src, src, v1
#endif
li v1, -EFAULT
- b .Ldone
+ b .Ldone\@
sw v1, (errptr)
-.Ls_exc:
+.Ls_exc\@:
li v0, -1 /* invalid checksum */
li v1, -EFAULT
jr ra
sw v1, (errptr)
.set pop
- END(__csum_partial_copy_user)
+ .endm
+
+LEAF(__csum_partial_copy_kernel)
+#ifndef CONFIG_EVA
+FEXPORT(__csum_partial_copy_to_user)
+FEXPORT(__csum_partial_copy_from_user)
+#endif
+__BUILD_CSUM_PARTIAL_COPY_USER LEGACY_MODE USEROP USEROP 1
+END(__csum_partial_copy_kernel)
+
+#ifdef CONFIG_EVA
+LEAF(__csum_partial_copy_to_user)
+__BUILD_CSUM_PARTIAL_COPY_USER EVA_MODE KERNELOP USEROP 0
+END(__csum_partial_copy_to_user)
+
+LEAF(__csum_partial_copy_from_user)
+__BUILD_CSUM_PARTIAL_COPY_USER EVA_MODE USEROP KERNELOP 0
+END(__csum_partial_copy_from_user)
+#endif
diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c
index 44713af15a6..21d27c6819a 100644
--- a/arch/mips/lib/delay.c
+++ b/arch/mips/lib/delay.c
@@ -6,29 +6,33 @@
* Copyright (C) 1994 by Waldorf Electronics
* Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2007 Maciej W. Rozycki
+ * Copyright (C) 2007, 2014 Maciej W. Rozycki
*/
#include <linux/module.h>
#include <linux/param.h>
#include <linux/smp.h>
+#include <linux/stringify.h>
+#include <asm/asm.h>
#include <asm/compiler.h>
#include <asm/war.h>
+#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
+#define GCC_DADDI_IMM_ASM() "I"
+#else
+#define GCC_DADDI_IMM_ASM() "r"
+#endif
+
void __delay(unsigned long loops)
{
__asm__ __volatile__ (
" .set noreorder \n"
" .align 3 \n"
"1: bnez %0, 1b \n"
-#if BITS_PER_LONG == 32
- " subu %0, 1 \n"
-#else
- " dsubu %0, 1 \n"
-#endif
+ " " __stringify(LONG_SUBU) " %0, %1 \n"
" .set reorder \n"
: "=r" (loops)
- : "0" (loops));
+ : GCC_DADDI_IMM_ASM() (1), "0" (loops));
}
EXPORT_SYMBOL(__delay);
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index c5c40dad0bb..c17ef80cf65 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -10,6 +10,7 @@
* Copyright (C) 2002 Broadcom, Inc.
* memcpy/copy_user author: Mark Vandevoorde
* Copyright (C) 2007 Maciej W. Rozycki
+ * Copyright (C) 2014 Imagination Technologies Ltd.
*
* Mnemonic names for arguments to memcpy/__copy_user
*/
@@ -85,11 +86,51 @@
* they're not protected.
*/
-#define EXC(inst_reg,addr,handler) \
-9: inst_reg, addr; \
- .section __ex_table,"a"; \
- PTR 9b, handler; \
- .previous
+/* Instruction type */
+#define LD_INSN 1
+#define ST_INSN 2
+/* Pretech type */
+#define SRC_PREFETCH 1
+#define DST_PREFETCH 2
+#define LEGACY_MODE 1
+#define EVA_MODE 2
+#define USEROP 1
+#define KERNELOP 2
+
+/*
+ * Wrapper to add an entry in the exception table
+ * in case the insn causes a memory exception.
+ * Arguments:
+ * insn : Load/store instruction
+ * type : Instruction type
+ * reg : Register
+ * addr : Address
+ * handler : Exception handler
+ */
+
+#define EXC(insn, type, reg, addr, handler) \
+ .if \mode == LEGACY_MODE; \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous; \
+ /* This is assembled in EVA mode */ \
+ .else; \
+ /* If loading from user or storing to user */ \
+ .if ((\from == USEROP) && (type == LD_INSN)) || \
+ ((\to == USEROP) && (type == ST_INSN)); \
+9: __BUILD_EVA_INSN(insn##e, reg, addr); \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous; \
+ .else; \
+ /* \
+ * Still in EVA, but no need for \
+ * exception handler or EVA insn \
+ */ \
+ insn reg, addr; \
+ .endif; \
+ .endif
/*
* Only on the 64-bit kernel we can made use of 64-bit registers.
@@ -100,12 +141,13 @@
#ifdef USE_DOUBLE
-#define LOAD ld
-#define LOADL ldl
-#define LOADR ldr
-#define STOREL sdl
-#define STORER sdr
-#define STORE sd
+#define LOADK ld /* No exception */
+#define LOAD(reg, addr, handler) EXC(ld, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler) EXC(ldl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler) EXC(ldr, LD_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler) EXC(sdl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler) EXC(sdr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler) EXC(sd, ST_INSN, reg, addr, handler)
#define ADD daddu
#define SUB dsubu
#define SRL dsrl
@@ -136,12 +178,13 @@
#else
-#define LOAD lw
-#define LOADL lwl
-#define LOADR lwr
-#define STOREL swl
-#define STORER swr
-#define STORE sw
+#define LOADK lw /* No exception */
+#define LOAD(reg, addr, handler) EXC(lw, LD_INSN, reg, addr, handler)
+#define LOADL(reg, addr, handler) EXC(lwl, LD_INSN, reg, addr, handler)
+#define LOADR(reg, addr, handler) EXC(lwr, LD_INSN, reg, addr, handler)
+#define STOREL(reg, addr, handler) EXC(swl, ST_INSN, reg, addr, handler)
+#define STORER(reg, addr, handler) EXC(swr, ST_INSN, reg, addr, handler)
+#define STORE(reg, addr, handler) EXC(sw, ST_INSN, reg, addr, handler)
#define ADD addu
#define SUB subu
#define SRL srl
@@ -154,6 +197,33 @@
#endif /* USE_DOUBLE */
+#define LOADB(reg, addr, handler) EXC(lb, LD_INSN, reg, addr, handler)
+#define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler)
+
+#define _PREF(hint, addr, type) \
+ .if \mode == LEGACY_MODE; \
+ PREF(hint, addr); \
+ .else; \
+ .if ((\from == USEROP) && (type == SRC_PREFETCH)) || \
+ ((\to == USEROP) && (type == DST_PREFETCH)); \
+ /* \
+ * PREFE has only 9 bits for the offset \
+ * compared to PREF which has 16, so it may \
+ * need to use the $at register but this \
+ * register should remain intact because it's \
+ * used later on. Therefore use $v1. \
+ */ \
+ .set at=v1; \
+ PREFE(hint, addr); \
+ .set noat; \
+ .else; \
+ PREF(hint, addr); \
+ .endif; \
+ .endif
+
+#define PREFS(hint, addr) _PREF(hint, addr, SRC_PREFETCH)
+#define PREFD(hint, addr) _PREF(hint, addr, DST_PREFETCH)
+
#ifdef CONFIG_CPU_LITTLE_ENDIAN
#define LDFIRST LOADR
#define LDREST LOADL
@@ -182,27 +252,23 @@
.set at=v1
#endif
-/*
- * t6 is used as a flag to note inatomic mode.
- */
-LEAF(__copy_user_inatomic)
- b __copy_user_common
- li t6, 1
- END(__copy_user_inatomic)
-
-/*
- * A combined memcpy/__copy_user
- * __copy_user sets len to 0 for success; else to an upper bound of
- * the number of uncopied bytes.
- * memcpy sets v0 to dst.
- */
.align 5
-LEAF(memcpy) /* a0=dst a1=src a2=len */
- move v0, dst /* return value */
-.L__memcpy:
-FEXPORT(__copy_user)
- li t6, 0 /* not inatomic */
-__copy_user_common:
+
+ /*
+ * Macro to build the __copy_user common code
+ * Arguements:
+ * mode : LEGACY_MODE or EVA_MODE
+ * from : Source operand. USEROP or KERNELOP
+ * to : Destination operand. USEROP or KERNELOP
+ */
+ .macro __BUILD_COPY_USER mode, from, to
+
+ /* initialize __memcpy if this the first time we execute this macro */
+ .ifnotdef __memcpy
+ .set __memcpy, 1
+ .hidden __memcpy /* make sure it does not leak */
+ .endif
+
/*
* Note: dst & src may be unaligned, len may be 0
* Temps
@@ -217,94 +283,94 @@ __copy_user_common:
*
* If len < NBYTES use byte operations.
*/
- PREF( 0, 0(src) )
- PREF( 1, 0(dst) )
+ PREFS( 0, 0(src) )
+ PREFD( 1, 0(dst) )
sltu t2, len, NBYTES
and t1, dst, ADDRMASK
- PREF( 0, 1*32(src) )
- PREF( 1, 1*32(dst) )
- bnez t2, .Lcopy_bytes_checklen
+ PREFS( 0, 1*32(src) )
+ PREFD( 1, 1*32(dst) )
+ bnez t2, .Lcopy_bytes_checklen\@
and t0, src, ADDRMASK
- PREF( 0, 2*32(src) )
- PREF( 1, 2*32(dst) )
- bnez t1, .Ldst_unaligned
+ PREFS( 0, 2*32(src) )
+ PREFD( 1, 2*32(dst) )
+ bnez t1, .Ldst_unaligned\@
nop
- bnez t0, .Lsrc_unaligned_dst_aligned
+ bnez t0, .Lsrc_unaligned_dst_aligned\@
/*
* use delay slot for fall-through
* src and dst are aligned; need to compute rem
*/
-.Lboth_aligned:
+.Lboth_aligned\@:
SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter
- beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES
+ beqz t0, .Lcleanup_both_aligned\@ # len < 8*NBYTES
and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES)
- PREF( 0, 3*32(src) )
- PREF( 1, 3*32(dst) )
+ PREFS( 0, 3*32(src) )
+ PREFD( 1, 3*32(dst) )
.align 4
1:
R10KCBARRIER(0(ra))
-EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
-EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
-EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
-EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
+ LOAD(t0, UNIT(0)(src), .Ll_exc\@)
+ LOAD(t1, UNIT(1)(src), .Ll_exc_copy\@)
+ LOAD(t2, UNIT(2)(src), .Ll_exc_copy\@)
+ LOAD(t3, UNIT(3)(src), .Ll_exc_copy\@)
SUB len, len, 8*NBYTES
-EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy)
-EXC( LOAD t7, UNIT(5)(src), .Ll_exc_copy)
-EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p8u)
-EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p7u)
-EXC( LOAD t0, UNIT(6)(src), .Ll_exc_copy)
-EXC( LOAD t1, UNIT(7)(src), .Ll_exc_copy)
+ LOAD(t4, UNIT(4)(src), .Ll_exc_copy\@)
+ LOAD(t7, UNIT(5)(src), .Ll_exc_copy\@)
+ STORE(t0, UNIT(0)(dst), .Ls_exc_p8u\@)
+ STORE(t1, UNIT(1)(dst), .Ls_exc_p7u\@)
+ LOAD(t0, UNIT(6)(src), .Ll_exc_copy\@)
+ LOAD(t1, UNIT(7)(src), .Ll_exc_copy\@)
ADD src, src, 8*NBYTES
ADD dst, dst, 8*NBYTES
-EXC( STORE t2, UNIT(-6)(dst), .Ls_exc_p6u)
-EXC( STORE t3, UNIT(-5)(dst), .Ls_exc_p5u)
-EXC( STORE t4, UNIT(-4)(dst), .Ls_exc_p4u)
-EXC( STORE t7, UNIT(-3)(dst), .Ls_exc_p3u)
-EXC( STORE t0, UNIT(-2)(dst), .Ls_exc_p2u)
-EXC( STORE t1, UNIT(-1)(dst), .Ls_exc_p1u)
- PREF( 0, 8*32(src) )
- PREF( 1, 8*32(dst) )
+ STORE(t2, UNIT(-6)(dst), .Ls_exc_p6u\@)
+ STORE(t3, UNIT(-5)(dst), .Ls_exc_p5u\@)
+ STORE(t4, UNIT(-4)(dst), .Ls_exc_p4u\@)
+ STORE(t7, UNIT(-3)(dst), .Ls_exc_p3u\@)
+ STORE(t0, UNIT(-2)(dst), .Ls_exc_p2u\@)
+ STORE(t1, UNIT(-1)(dst), .Ls_exc_p1u\@)
+ PREFS( 0, 8*32(src) )
+ PREFD( 1, 8*32(dst) )
bne len, rem, 1b
nop
/*
* len == rem == the number of bytes left to copy < 8*NBYTES
*/
-.Lcleanup_both_aligned:
- beqz len, .Ldone
+.Lcleanup_both_aligned\@:
+ beqz len, .Ldone\@
sltu t0, len, 4*NBYTES
- bnez t0, .Lless_than_4units
+ bnez t0, .Lless_than_4units\@
and rem, len, (NBYTES-1) # rem = len % NBYTES
/*
* len >= 4*NBYTES
*/
-EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
-EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
-EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
-EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
+ LOAD( t0, UNIT(0)(src), .Ll_exc\@)
+ LOAD( t1, UNIT(1)(src), .Ll_exc_copy\@)
+ LOAD( t2, UNIT(2)(src), .Ll_exc_copy\@)
+ LOAD( t3, UNIT(3)(src), .Ll_exc_copy\@)
SUB len, len, 4*NBYTES
ADD src, src, 4*NBYTES
R10KCBARRIER(0(ra))
-EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p4u)
-EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p3u)
-EXC( STORE t2, UNIT(2)(dst), .Ls_exc_p2u)
-EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u)
+ STORE(t0, UNIT(0)(dst), .Ls_exc_p4u\@)
+ STORE(t1, UNIT(1)(dst), .Ls_exc_p3u\@)
+ STORE(t2, UNIT(2)(dst), .Ls_exc_p2u\@)
+ STORE(t3, UNIT(3)(dst), .Ls_exc_p1u\@)
.set reorder /* DADDI_WAR */
ADD dst, dst, 4*NBYTES
- beqz len, .Ldone
+ beqz len, .Ldone\@
.set noreorder
-.Lless_than_4units:
+.Lless_than_4units\@:
/*
* rem = len % NBYTES
*/
- beq rem, len, .Lcopy_bytes
+ beq rem, len, .Lcopy_bytes\@
nop
1:
R10KCBARRIER(0(ra))
-EXC( LOAD t0, 0(src), .Ll_exc)
+ LOAD(t0, 0(src), .Ll_exc\@)
ADD src, src, NBYTES
SUB len, len, NBYTES
-EXC( STORE t0, 0(dst), .Ls_exc_p1u)
+ STORE(t0, 0(dst), .Ls_exc_p1u\@)
.set reorder /* DADDI_WAR */
ADD dst, dst, NBYTES
bne rem, len, 1b
@@ -322,17 +388,17 @@ EXC( STORE t0, 0(dst), .Ls_exc_p1u)
* more instruction-level parallelism.
*/
#define bits t2
- beqz len, .Ldone
+ beqz len, .Ldone\@
ADD t1, dst, len # t1 is just past last byte of dst
li bits, 8*NBYTES
SLL rem, len, 3 # rem = number of bits to keep
-EXC( LOAD t0, 0(src), .Ll_exc)
+ LOAD(t0, 0(src), .Ll_exc\@)
SUB bits, bits, rem # bits = number of bits to discard
SHIFT_DISCARD t0, t0, bits
-EXC( STREST t0, -1(t1), .Ls_exc)
+ STREST(t0, -1(t1), .Ls_exc\@)
jr ra
move len, zero
-.Ldst_unaligned:
+.Ldst_unaligned\@:
/*
* dst is unaligned
* t0 = src & ADDRMASK
@@ -343,25 +409,25 @@ EXC( STREST t0, -1(t1), .Ls_exc)
* Set match = (src and dst have same alignment)
*/
#define match rem
-EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc)
+ LDFIRST(t3, FIRST(0)(src), .Ll_exc\@)
ADD t2, zero, NBYTES
-EXC( LDREST t3, REST(0)(src), .Ll_exc_copy)
+ LDREST(t3, REST(0)(src), .Ll_exc_copy\@)
SUB t2, t2, t1 # t2 = number of bytes copied
xor match, t0, t1
R10KCBARRIER(0(ra))
-EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc)
- beq len, t2, .Ldone
+ STFIRST(t3, FIRST(0)(dst), .Ls_exc\@)
+ beq len, t2, .Ldone\@
SUB len, len, t2
ADD dst, dst, t2
- beqz match, .Lboth_aligned
+ beqz match, .Lboth_aligned\@
ADD src, src, t2
-.Lsrc_unaligned_dst_aligned:
+.Lsrc_unaligned_dst_aligned\@:
SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
- PREF( 0, 3*32(src) )
- beqz t0, .Lcleanup_src_unaligned
+ PREFS( 0, 3*32(src) )
+ beqz t0, .Lcleanup_src_unaligned\@
and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
- PREF( 1, 3*32(dst) )
+ PREFD( 1, 3*32(dst) )
1:
/*
* Avoid consecutive LD*'s to the same register since some mips
@@ -370,58 +436,58 @@ EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc)
* are to the same unit (unless src is aligned, but it's not).
*/
R10KCBARRIER(0(ra))
-EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
-EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy)
+ LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+ LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy\@)
SUB len, len, 4*NBYTES
-EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
-EXC( LDREST t1, REST(1)(src), .Ll_exc_copy)
-EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy)
-EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy)
-EXC( LDREST t2, REST(2)(src), .Ll_exc_copy)
-EXC( LDREST t3, REST(3)(src), .Ll_exc_copy)
- PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed)
+ LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
+ LDREST(t1, REST(1)(src), .Ll_exc_copy\@)
+ LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy\@)
+ LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy\@)
+ LDREST(t2, REST(2)(src), .Ll_exc_copy\@)
+ LDREST(t3, REST(3)(src), .Ll_exc_copy\@)
+ PREFS( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed)
ADD src, src, 4*NBYTES
#ifdef CONFIG_CPU_SB1
nop # improves slotting
#endif
-EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p4u)
-EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p3u)
-EXC( STORE t2, UNIT(2)(dst), .Ls_exc_p2u)
-EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u)
- PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed)
+ STORE(t0, UNIT(0)(dst), .Ls_exc_p4u\@)
+ STORE(t1, UNIT(1)(dst), .Ls_exc_p3u\@)
+ STORE(t2, UNIT(2)(dst), .Ls_exc_p2u\@)
+ STORE(t3, UNIT(3)(dst), .Ls_exc_p1u\@)
+ PREFD( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed)
.set reorder /* DADDI_WAR */
ADD dst, dst, 4*NBYTES
bne len, rem, 1b
.set noreorder
-.Lcleanup_src_unaligned:
- beqz len, .Ldone
+.Lcleanup_src_unaligned\@:
+ beqz len, .Ldone\@
and rem, len, NBYTES-1 # rem = len % NBYTES
- beq rem, len, .Lcopy_bytes
+ beq rem, len, .Lcopy_bytes\@
nop
1:
R10KCBARRIER(0(ra))
-EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
-EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
+ LDFIRST(t0, FIRST(0)(src), .Ll_exc\@)
+ LDREST(t0, REST(0)(src), .Ll_exc_copy\@)
ADD src, src, NBYTES
SUB len, len, NBYTES
-EXC( STORE t0, 0(dst), .Ls_exc_p1u)
+ STORE(t0, 0(dst), .Ls_exc_p1u\@)
.set reorder /* DADDI_WAR */
ADD dst, dst, NBYTES
bne len, rem, 1b
.set noreorder
-.Lcopy_bytes_checklen:
- beqz len, .Ldone
+.Lcopy_bytes_checklen\@:
+ beqz len, .Ldone\@
nop
-.Lcopy_bytes:
+.Lcopy_bytes\@:
/* 0 < len < NBYTES */
R10KCBARRIER(0(ra))
#define COPY_BYTE(N) \
-EXC( lb t0, N(src), .Ll_exc); \
+ LOADB(t0, N(src), .Ll_exc\@); \
SUB len, len, 1; \
- beqz len, .Ldone; \
-EXC( sb t0, N(dst), .Ls_exc_p1)
+ beqz len, .Ldone\@; \
+ STOREB(t0, N(dst), .Ls_exc_p1\@)
COPY_BYTE(0)
COPY_BYTE(1)
@@ -431,16 +497,19 @@ EXC( sb t0, N(dst), .Ls_exc_p1)
COPY_BYTE(4)
COPY_BYTE(5)
#endif
-EXC( lb t0, NBYTES-2(src), .Ll_exc)
+ LOADB(t0, NBYTES-2(src), .Ll_exc\@)
SUB len, len, 1
jr ra
-EXC( sb t0, NBYTES-2(dst), .Ls_exc_p1)
-.Ldone:
+ STOREB(t0, NBYTES-2(dst), .Ls_exc_p1\@)
+.Ldone\@:
jr ra
- nop
+ .if __memcpy == 1
END(memcpy)
+ .set __memcpy, 0
+ .hidden __memcpy
+ .endif
-.Ll_exc_copy:
+.Ll_exc_copy\@:
/*
* Copy bytes from src until faulting load address (or until a
* lb faults)
@@ -451,24 +520,24 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc_p1)
*
* Assumes src < THREAD_BUADDR($28)
*/
- LOAD t0, TI_TASK($28)
+ LOADK t0, TI_TASK($28)
nop
- LOAD t0, THREAD_BUADDR(t0)
+ LOADK t0, THREAD_BUADDR(t0)
1:
-EXC( lb t1, 0(src), .Ll_exc)
+ LOADB(t1, 0(src), .Ll_exc\@)
ADD src, src, 1
sb t1, 0(dst) # can't fault -- we're copy_from_user
.set reorder /* DADDI_WAR */
ADD dst, dst, 1
bne src, t0, 1b
.set noreorder
-.Ll_exc:
- LOAD t0, TI_TASK($28)
+.Ll_exc\@:
+ LOADK t0, TI_TASK($28)
nop
- LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
+ LOADK t0, THREAD_BUADDR(t0) # t0 is just past last good address
nop
SUB len, AT, t0 # len number of uncopied bytes
- bnez t6, .Ldone /* Skip the zeroing part if inatomic */
+ bnez t6, .Ldone\@ /* Skip the zeroing part if inatomic */
/*
* Here's where we rely on src and dst being incremented in tandem,
* See (3) above.
@@ -482,7 +551,7 @@ EXC( lb t1, 0(src), .Ll_exc)
*/
.set reorder /* DADDI_WAR */
SUB src, len, 1
- beqz len, .Ldone
+ beqz len, .Ldone\@
.set noreorder
1: sb zero, 0(dst)
ADD dst, dst, 1
@@ -503,7 +572,7 @@ EXC( lb t1, 0(src), .Ll_exc)
#define SEXC(n) \
.set reorder; /* DADDI_WAR */ \
-.Ls_exc_p ## n ## u: \
+.Ls_exc_p ## n ## u\@: \
ADD len, len, n*NBYTES; \
jr ra; \
.set noreorder
@@ -517,14 +586,15 @@ SEXC(3)
SEXC(2)
SEXC(1)
-.Ls_exc_p1:
+.Ls_exc_p1\@:
.set reorder /* DADDI_WAR */
ADD len, len, 1
jr ra
.set noreorder
-.Ls_exc:
+.Ls_exc\@:
jr ra
nop
+ .endm
.align 5
LEAF(memmove)
@@ -575,3 +645,71 @@ LEAF(__rmemcpy) /* a0=dst a1=src a2=len */
jr ra
move a2, zero
END(__rmemcpy)
+
+/*
+ * t6 is used as a flag to note inatomic mode.
+ */
+LEAF(__copy_user_inatomic)
+ b __copy_user_common
+ li t6, 1
+ END(__copy_user_inatomic)
+
+/*
+ * A combined memcpy/__copy_user
+ * __copy_user sets len to 0 for success; else to an upper bound of
+ * the number of uncopied bytes.
+ * memcpy sets v0 to dst.
+ */
+ .align 5
+LEAF(memcpy) /* a0=dst a1=src a2=len */
+ move v0, dst /* return value */
+.L__memcpy:
+FEXPORT(__copy_user)
+ li t6, 0 /* not inatomic */
+__copy_user_common:
+ /* Legacy Mode, user <-> user */
+ __BUILD_COPY_USER LEGACY_MODE USEROP USEROP
+
+#ifdef CONFIG_EVA
+
+/*
+ * For EVA we need distinct symbols for reading and writing to user space.
+ * This is because we need to use specific EVA instructions to perform the
+ * virtual <-> physical translation when a virtual address is actually in user
+ * space
+ */
+
+LEAF(__copy_user_inatomic_eva)
+ b __copy_from_user_common
+ li t6, 1
+ END(__copy_user_inatomic_eva)
+
+/*
+ * __copy_from_user (EVA)
+ */
+
+LEAF(__copy_from_user_eva)
+ li t6, 0 /* not inatomic */
+__copy_from_user_common:
+ __BUILD_COPY_USER EVA_MODE USEROP KERNELOP
+END(__copy_from_user_eva)
+
+
+
+/*
+ * __copy_to_user (EVA)
+ */
+
+LEAF(__copy_to_user_eva)
+__BUILD_COPY_USER EVA_MODE KERNELOP USEROP
+END(__copy_to_user_eva)
+
+/*
+ * __copy_in_user (EVA)
+ */
+
+LEAF(__copy_in_user_eva)
+__BUILD_COPY_USER EVA_MODE USEROP USEROP
+END(__copy_in_user_eva)
+
+#endif
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index 0580194e740..7b0e5462ca5 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -34,13 +34,27 @@
#define FILLPTRG t0
#endif
+#define LEGACY_MODE 1
+#define EVA_MODE 2
+
+/*
+ * No need to protect it with EVA #ifdefery. The generated block of code
+ * will never be assembled if EVA is not enabled.
+ */
+#define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr)
+#define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr)
+
#define EX(insn,reg,addr,handler) \
-9: insn reg, addr; \
+ .if \mode == LEGACY_MODE; \
+9: insn reg, addr; \
+ .else; \
+9: ___BUILD_EVA_INSN(insn, reg, addr); \
+ .endif; \
.section __ex_table,"a"; \
PTR 9b, handler; \
.previous
- .macro f_fill64 dst, offset, val, fixup
+ .macro f_fill64 dst, offset, val, fixup, mode
EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup)
EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup)
EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup)
@@ -63,34 +77,24 @@
#endif
.endm
-/*
- * memset(void *s, int c, size_t n)
- *
- * a0: start of area to clear
- * a1: char to fill with
- * a2: size of area to clear
- */
.set noreorder
.align 5
-LEAF(memset)
- beqz a1, 1f
- move v0, a0 /* result */
- andi a1, 0xff /* spread fillword */
- LONG_SLL t1, a1, 8
- or a1, t1
- LONG_SLL t1, a1, 16
-#if LONGSIZE == 8
- or a1, t1
- LONG_SLL t1, a1, 32
-#endif
- or a1, t1
-1:
+ /*
+ * Macro to generate the __bzero{,_user} symbol
+ * Arguments:
+ * mode: LEGACY_MODE or EVA_MODE
+ */
+ .macro __BUILD_BZERO mode
+ /* Initialize __memset if this is the first time we call this macro */
+ .ifnotdef __memset
+ .set __memset, 1
+ .hidden __memset /* Make sure it does not leak */
+ .endif
-FEXPORT(__bzero)
sltiu t0, a2, STORSIZE /* very small region? */
- bnez t0, .Lsmall_memset
- andi t0, a0, STORMASK /* aligned? */
+ bnez t0, .Lsmall_memset\@
+ andi t0, a0, STORMASK /* aligned? */
#ifdef CONFIG_CPU_MICROMIPS
move t8, a1 /* used by 'swp' instruction */
@@ -98,39 +102,39 @@ FEXPORT(__bzero)
#endif
#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
beqz t0, 1f
- PTR_SUBU t0, STORSIZE /* alignment in bytes */
+ PTR_SUBU t0, STORSIZE /* alignment in bytes */
#else
.set noat
li AT, STORSIZE
beqz t0, 1f
- PTR_SUBU t0, AT /* alignment in bytes */
+ PTR_SUBU t0, AT /* alignment in bytes */
.set at
#endif
R10KCBARRIER(0(ra))
#ifdef __MIPSEB__
- EX(LONG_S_L, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */
+ EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
#endif
#ifdef __MIPSEL__
- EX(LONG_S_R, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */
+ EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
#endif
PTR_SUBU a0, t0 /* long align ptr */
PTR_ADDU a2, t0 /* correct size */
1: ori t1, a2, 0x3f /* # of full blocks */
xori t1, 0x3f
- beqz t1, .Lmemset_partial /* no block to fill */
- andi t0, a2, 0x40-STORSIZE
+ beqz t1, .Lmemset_partial\@ /* no block to fill */
+ andi t0, a2, 0x40-STORSIZE
PTR_ADDU t1, a0 /* end address */
.set reorder
1: PTR_ADDIU a0, 64
R10KCBARRIER(0(ra))
- f_fill64 a0, -64, FILL64RG, .Lfwd_fixup
+ f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode
bne t1, a0, 1b
.set noreorder
-.Lmemset_partial:
+.Lmemset_partial\@:
R10KCBARRIER(0(ra))
PTR_LA t1, 2f /* where to start */
#ifdef CONFIG_CPU_MICROMIPS
@@ -145,60 +149,100 @@ FEXPORT(__bzero)
.set at
#endif
jr t1
- PTR_ADDU a0, t0 /* dest ptr */
+ PTR_ADDU a0, t0 /* dest ptr */
.set push
.set noreorder
.set nomacro
- f_fill64 a0, -64, FILL64RG, .Lpartial_fixup /* ... but first do longs ... */
+ /* ... but first do longs ... */
+ f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode
2: .set pop
andi a2, STORMASK /* At most one long to go */
beqz a2, 1f
- PTR_ADDU a0, a2 /* What's left */
+ PTR_ADDU a0, a2 /* What's left */
R10KCBARRIER(0(ra))
#ifdef __MIPSEB__
- EX(LONG_S_R, a1, -1(a0), .Llast_fixup)
+ EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
#endif
#ifdef __MIPSEL__
- EX(LONG_S_L, a1, -1(a0), .Llast_fixup)
+ EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
#endif
1: jr ra
- move a2, zero
+ move a2, zero
-.Lsmall_memset:
+.Lsmall_memset\@:
beqz a2, 2f
- PTR_ADDU t1, a0, a2
+ PTR_ADDU t1, a0, a2
1: PTR_ADDIU a0, 1 /* fill bytewise */
R10KCBARRIER(0(ra))
bne t1, a0, 1b
- sb a1, -1(a0)
+ sb a1, -1(a0)
2: jr ra /* done */
- move a2, zero
+ move a2, zero
+ .if __memset == 1
END(memset)
+ .set __memset, 0
+ .hidden __memset
+ .endif
-.Lfirst_fixup:
+.Lfirst_fixup\@:
jr ra
- nop
+ nop
-.Lfwd_fixup:
+.Lfwd_fixup\@:
PTR_L t0, TI_TASK($28)
andi a2, 0x3f
LONG_L t0, THREAD_BUADDR(t0)
LONG_ADDU a2, t1
jr ra
- LONG_SUBU a2, t0
+ LONG_SUBU a2, t0
-.Lpartial_fixup:
+.Lpartial_fixup\@:
PTR_L t0, TI_TASK($28)
andi a2, STORMASK
LONG_L t0, THREAD_BUADDR(t0)
LONG_ADDU a2, t1
jr ra
- LONG_SUBU a2, t0
+ LONG_SUBU a2, t0
-.Llast_fixup:
+.Llast_fixup\@:
jr ra
- andi v1, a2, STORMASK
+ andi v1, a2, STORMASK
+
+ .endm
+
+/*
+ * memset(void *s, int c, size_t n)
+ *
+ * a0: start of area to clear
+ * a1: char to fill with
+ * a2: size of area to clear
+ */
+
+LEAF(memset)
+ beqz a1, 1f
+ move v0, a0 /* result */
+
+ andi a1, 0xff /* spread fillword */
+ LONG_SLL t1, a1, 8
+ or a1, t1
+ LONG_SLL t1, a1, 16
+#if LONGSIZE == 8
+ or a1, t1
+ LONG_SLL t1, a1, 32
+#endif
+ or a1, t1
+1:
+#ifndef CONFIG_EVA
+FEXPORT(__bzero)
+#endif
+ __BUILD_BZERO LEGACY_MODE
+
+#ifdef CONFIG_EVA
+LEAF(__bzero)
+ __BUILD_BZERO EVA_MODE
+END(__bzero)
+#endif
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
index 6807f7172ea..57bcdaf1f1c 100644
--- a/arch/mips/lib/mips-atomic.c
+++ b/arch/mips/lib/mips-atomic.c
@@ -15,7 +15,7 @@
#include <linux/export.h>
#include <linux/stringify.h>
-#if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC)
+#ifndef CONFIG_CPU_MIPSR2
/*
* For cli() we have to insert nops to make sure that the new value
@@ -42,12 +42,7 @@ notrace void arch_local_irq_disable(void)
__asm__ __volatile__(
" .set push \n"
" .set noat \n"
-#ifdef CONFIG_MIPS_MT_SMTC
- " mfc0 $1, $2, 1 \n"
- " ori $1, 0x400 \n"
- " .set noreorder \n"
- " mtc0 $1, $2, 1 \n"
-#elif defined(CONFIG_CPU_MIPSR2)
+#if defined(CONFIG_CPU_MIPSR2)
/* see irqflags.h for inline function */
#else
" mfc0 $1,$12 \n"
@@ -77,13 +72,7 @@ notrace unsigned long arch_local_irq_save(void)
" .set push \n"
" .set reorder \n"
" .set noat \n"
-#ifdef CONFIG_MIPS_MT_SMTC
- " mfc0 %[flags], $2, 1 \n"
- " ori $1, %[flags], 0x400 \n"
- " .set noreorder \n"
- " mtc0 $1, $2, 1 \n"
- " andi %[flags], %[flags], 0x400 \n"
-#elif defined(CONFIG_CPU_MIPSR2)
+#if defined(CONFIG_CPU_MIPSR2)
/* see irqflags.h for inline function */
#else
" mfc0 %[flags], $12 \n"
@@ -108,29 +97,13 @@ notrace void arch_local_irq_restore(unsigned long flags)
{
unsigned long __tmp1;
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC kernel needs to do a software replay of queued
- * IPIs, at the cost of branch and call overhead on each
- * local_irq_restore()
- */
- if (unlikely(!(flags & 0x0400)))
- smtc_ipi_replay();
-#endif
preempt_disable();
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#ifdef CONFIG_MIPS_MT_SMTC
- " mfc0 $1, $2, 1 \n"
- " andi %[flags], 0x400 \n"
- " ori $1, 0x400 \n"
- " xori $1, 0x400 \n"
- " or %[flags], $1 \n"
- " mtc0 %[flags], $2, 1 \n"
-#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
/* see irqflags.h for inline function */
#elif defined(CONFIG_CPU_MIPSR2)
/* see irqflags.h for inline function */
@@ -163,14 +136,7 @@ notrace void __arch_local_irq_restore(unsigned long flags)
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#ifdef CONFIG_MIPS_MT_SMTC
- " mfc0 $1, $2, 1 \n"
- " andi %[flags], 0x400 \n"
- " ori $1, 0x400 \n"
- " xori $1, 0x400 \n"
- " or %[flags], $1 \n"
- " mtc0 %[flags], $2, 1 \n"
-#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
/* see irqflags.h for inline function */
#elif defined(CONFIG_CPU_MIPSR2)
/* see irqflags.h for inline function */
@@ -192,4 +158,4 @@ notrace void __arch_local_irq_restore(unsigned long flags)
}
EXPORT_SYMBOL(__arch_local_irq_restore);
-#endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */
+#endif /* !CONFIG_CPU_MIPSR2 */
diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S
index e362dcdc69d..bef65c98df5 100644
--- a/arch/mips/lib/strlen_user.S
+++ b/arch/mips/lib/strlen_user.S
@@ -22,19 +22,43 @@
*
* Return 0 for error
*/
-LEAF(__strlen_user_asm)
+ .macro __BUILD_STRLEN_ASM func
+LEAF(__strlen_\func\()_asm)
LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok?
and v0, a0
- bnez v0, .Lfault
+ bnez v0, .Lfault\@
-FEXPORT(__strlen_user_nocheck_asm)
+FEXPORT(__strlen_\func\()_nocheck_asm)
move v0, a0
-1: EX(lbu, v1, (v0), .Lfault)
+.ifeqs "\func", "kernel"
+1: EX(lbu, v1, (v0), .Lfault\@)
+.else
+1: EX(lbue, v1, (v0), .Lfault\@)
+.endif
PTR_ADDIU v0, 1
bnez v1, 1b
PTR_SUBU v0, a0
jr ra
- END(__strlen_user_asm)
+ END(__strlen_\func\()_asm)
-.Lfault: move v0, zero
+.Lfault\@: move v0, zero
jr ra
+ .endm
+
+#ifndef CONFIG_EVA
+ /* Set aliases */
+ .global __strlen_user_asm
+ .global __strlen_user_nocheck_asm
+ .set __strlen_user_asm, __strlen_kernel_asm
+ .set __strlen_user_nocheck_asm, __strlen_kernel_nocheck_asm
+#endif
+
+__BUILD_STRLEN_ASM kernel
+
+#ifdef CONFIG_EVA
+
+ .set push
+ .set eva
+__BUILD_STRLEN_ASM user
+ .set pop
+#endif
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
index 92870b6b53e..3c32baf8b49 100644
--- a/arch/mips/lib/strncpy_user.S
+++ b/arch/mips/lib/strncpy_user.S
@@ -28,34 +28,57 @@
* it happens at most some bytes of the exceptions handlers will be copied.
*/
-LEAF(__strncpy_from_user_asm)
+ .macro __BUILD_STRNCPY_ASM func
+LEAF(__strncpy_from_\func\()_asm)
LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok?
and v0, a1
- bnez v0, .Lfault
+ bnez v0, .Lfault\@
-FEXPORT(__strncpy_from_user_nocheck_asm)
- .set noreorder
+FEXPORT(__strncpy_from_\func\()_nocheck_asm)
move t0, zero
move v1, a1
-1: EX(lbu, v0, (v1), .Lfault)
+.ifeqs "\func","kernel"
+1: EX(lbu, v0, (v1), .Lfault\@)
+.else
+1: EX(lbue, v0, (v1), .Lfault\@)
+.endif
PTR_ADDIU v1, 1
R10KCBARRIER(0(ra))
+ sb v0, (a0)
beqz v0, 2f
- sb v0, (a0)
PTR_ADDIU t0, 1
+ PTR_ADDIU a0, 1
bne t0, a2, 1b
- PTR_ADDIU a0, 1
2: PTR_ADDU v0, a1, t0
xor v0, a1
- bltz v0, .Lfault
- nop
+ bltz v0, .Lfault\@
+ move v0, t0
jr ra # return n
- move v0, t0
- END(__strncpy_from_user_asm)
+ END(__strncpy_from_\func\()_asm)
-.Lfault: jr ra
- li v0, -EFAULT
+.Lfault\@:
+ li v0, -EFAULT
+ jr ra
.section __ex_table,"a"
- PTR 1b, .Lfault
+ PTR 1b, .Lfault\@
.previous
+
+ .endm
+
+#ifndef CONFIG_EVA
+ /* Set aliases */
+ .global __strncpy_from_user_asm
+ .global __strncpy_from_user_nocheck_asm
+ .set __strncpy_from_user_asm, __strncpy_from_kernel_asm
+ .set __strncpy_from_user_nocheck_asm, __strncpy_from_kernel_nocheck_asm
+#endif
+
+__BUILD_STRNCPY_ASM kernel
+
+#ifdef CONFIG_EVA
+ .set push
+ .set eva
+__BUILD_STRNCPY_ASM user
+ .set pop
+#endif
diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S
index fcacea5e61f..f3af6995e2a 100644
--- a/arch/mips/lib/strnlen_user.S
+++ b/arch/mips/lib/strnlen_user.S
@@ -25,22 +25,46 @@
* bytes. There's nothing secret there. On 64-bit accessing beyond
* the maximum is a tad hairier ...
*/
-LEAF(__strnlen_user_asm)
+ .macro __BUILD_STRNLEN_ASM func
+LEAF(__strnlen_\func\()_asm)
LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok?
and v0, a0
- bnez v0, .Lfault
+ bnez v0, .Lfault\@
-FEXPORT(__strnlen_user_nocheck_asm)
+FEXPORT(__strnlen_\func\()_nocheck_asm)
move v0, a0
PTR_ADDU a1, a0 # stop pointer
1: beq v0, a1, 1f # limit reached?
- EX(lb, t0, (v0), .Lfault)
+.ifeqs "\func", "kernel"
+ EX(lb, t0, (v0), .Lfault\@)
+.else
+ EX(lbe, t0, (v0), .Lfault\@)
+.endif
PTR_ADDIU v0, 1
bnez t0, 1b
1: PTR_SUBU v0, a0
jr ra
- END(__strnlen_user_asm)
+ END(__strnlen_\func\()_asm)
-.Lfault:
+.Lfault\@:
move v0, zero
jr ra
+ .endm
+
+#ifndef CONFIG_EVA
+ /* Set aliases */
+ .global __strnlen_user_asm
+ .global __strnlen_user_nocheck_asm
+ .set __strnlen_user_asm, __strnlen_kernel_asm
+ .set __strnlen_user_nocheck_asm, __strnlen_kernel_nocheck_asm
+#endif
+
+__BUILD_STRNLEN_ASM kernel
+
+#ifdef CONFIG_EVA
+
+ .set push
+ .set eva
+__BUILD_STRNLEN_ASM user
+ .set pop
+#endif
diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c
index d8522f8e842..09d5deea747 100644
--- a/arch/mips/lib/uncached.c
+++ b/arch/mips/lib/uncached.c
@@ -8,7 +8,6 @@
* Author: Maciej W. Rozycki <macro@mips.com>
*/
-#include <linux/init.h>
#include <asm/addrspace.h>
#include <asm/bug.h>
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 263beb9322a..e6a86ccc442 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -59,6 +59,35 @@ config LEMOTE_MACH2F
These family machines include fuloong2f mini PC, yeeloong2f notebook,
LingLoong allinone PC and so forth.
+
+config LEMOTE_MACH3A
+ bool "Lemote Loongson 3A family machines"
+ select ARCH_SPARSEMEM_ENABLE
+ select GENERIC_ISA_DMA_SUPPORT_BROKEN
+ select BOOT_ELF32
+ select BOARD_SCACHE
+ select CSRC_R4K
+ select CEVT_R4K
+ select CPU_HAS_WB
+ select HW_HAS_PCI
+ select ISA
+ select HT_PCI
+ select I8259
+ select IRQ_CPU
+ select NR_CPUS_DEFAULT_4
+ select SYS_HAS_CPU_LOONGSON3
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_HOTPLUG_CPU
+ select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_HIGHMEM
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select LOONGSON_MC146818
+ select ZONE_DMA32
+ select LEFI_FIRMWARE_INTERFACE
+ help
+ Lemote Loongson 3A family machines utilize the 3A revision of
+ Loongson processor and RS780/SBX00 chipset.
endchoice
config CS5536
@@ -66,10 +95,11 @@ config CS5536
config CS5536_MFGPT
bool "CS5536 MFGPT Timer"
- depends on CS5536
+ depends on CS5536 && !HIGH_RES_TIMERS
select MIPS_EXTERNAL_TIMER
help
- This option enables the mfgpt0 timer of AMD CS5536.
+ This option enables the mfgpt0 timer of AMD CS5536. With this timer
+ switched on you can not use high resolution timers.
If you want to enable the Loongson2 CPUFreq Driver, Please enable
this option at first, otherwise, You will get wrong system time.
@@ -86,8 +116,25 @@ config LOONGSON_UART_BASE
default y
depends on EARLY_PRINTK || SERIAL_8250
+config IOMMU_HELPER
+ bool
+
+config NEED_SG_DMA_LENGTH
+ bool
+
+config SWIOTLB
+ bool "Soft IOMMU Support for All-Memory DMA"
+ default y
+ depends on CPU_LOONGSON3
+ select IOMMU_HELPER
+ select NEED_SG_DMA_LENGTH
+ select NEED_DMA_MAP_STATE
+
config LOONGSON_MC146818
bool
default n
+config LEFI_FIRMWARE_INTERFACE
+ bool
+
endif # MACH_LOONGSON
diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
index 0dc0055754c..7429994e760 100644
--- a/arch/mips/loongson/Makefile
+++ b/arch/mips/loongson/Makefile
@@ -15,3 +15,9 @@ obj-$(CONFIG_LEMOTE_FULOONG2E) += fuloong-2e/
#
obj-$(CONFIG_LEMOTE_MACH2F) += lemote-2f/
+
+#
+# All Loongson-3 family machines
+#
+
+obj-$(CONFIG_CPU_LOONGSON3) += loongson-3/
diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
index 29692e5433b..6205372b6c2 100644
--- a/arch/mips/loongson/Platform
+++ b/arch/mips/loongson/Platform
@@ -30,3 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
+load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index 9e4484ccbb0..0bb9cc9dc62 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
#
obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+
+#
+# Big Memory (SWIOTLB) Support
+#
+obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
index c639b9db001..12c75db2342 100644
--- a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
+++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
@@ -27,8 +27,7 @@
#include <cs5536/cs5536_mfgpt.h>
-DEFINE_SPINLOCK(mfgpt_lock);
-EXPORT_SYMBOL(mfgpt_lock);
+static DEFINE_RAW_SPINLOCK(mfgpt_lock);
static u32 mfgpt_base;
@@ -55,7 +54,7 @@ EXPORT_SYMBOL(enable_mfgpt0_counter);
static void init_mfgpt_timer(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- spin_lock(&mfgpt_lock);
+ raw_spin_lock(&mfgpt_lock);
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
@@ -79,7 +78,7 @@ static void init_mfgpt_timer(enum clock_event_mode mode,
/* Nothing to do here */
break;
}
- spin_unlock(&mfgpt_lock);
+ raw_spin_unlock(&mfgpt_lock);
}
static struct clock_event_device mfgpt_clockevent = {
@@ -157,7 +156,7 @@ static cycle_t mfgpt_read(struct clocksource *cs)
static int old_count;
static u32 old_jifs;
- spin_lock_irqsave(&mfgpt_lock, flags);
+ raw_spin_lock_irqsave(&mfgpt_lock, flags);
/*
* Although our caller may have the read side of xtime_lock,
* this is now a seqlock, and we are cheating in this routine
@@ -191,7 +190,7 @@ static cycle_t mfgpt_read(struct clocksource *cs)
old_count = count;
old_jifs = jifs;
- spin_unlock_irqrestore(&mfgpt_lock, flags);
+ raw_spin_unlock_irqrestore(&mfgpt_lock, flags);
return (cycle_t) (jifs * COMPARE) + count;
}
diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c
new file mode 100644
index 00000000000..c2be01f9157
--- /dev/null
+++ b/arch/mips/loongson/common/dma-swiotlb.c
@@ -0,0 +1,136 @@
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/swiotlb.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <boot_param.h>
+#include <dma-coherence.h>
+
+static void *loongson_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);
+
+#ifdef CONFIG_ISA
+ if (dev == NULL)
+ gfp |= __GFP_DMA;
+ else
+#endif
+#ifdef CONFIG_ZONE_DMA
+ if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
+ gfp |= __GFP_DMA;
+ else
+#endif
+#ifdef CONFIG_ZONE_DMA32
+ if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
+ gfp |= __GFP_DMA32;
+ else
+#endif
+ ;
+ gfp |= __GFP_NORETRY;
+
+ ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
+ mb();
+ return ret;
+}
+
+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);
+}
+
+static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
+ dir, attrs);
+ mb();
+ return daddr;
+}
+
+static int loongson_dma_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
+ mb();
+
+ return r;
+}
+
+static void loongson_dma_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
+ mb();
+}
+
+static void loongson_dma_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ swiotlb_sync_sg_for_device(dev, sg, nents, dir);
+ mb();
+}
+
+static int loongson_dma_set_mask(struct device *dev, u64 mask)
+{
+ if (mask > DMA_BIT_MASK(loongson_sysconf.dma_mask_bits)) {
+ *dev->dma_mask = DMA_BIT_MASK(loongson_sysconf.dma_mask_bits);
+ return -EIO;
+ }
+
+ *dev->dma_mask = mask;
+
+ return 0;
+}
+
+dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+ return paddr;
+}
+
+phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+ return daddr;
+}
+
+static struct dma_map_ops loongson_dma_map_ops = {
+ .alloc = loongson_dma_alloc_coherent,
+ .free = loongson_dma_free_coherent,
+ .map_page = loongson_dma_map_page,
+ .unmap_page = swiotlb_unmap_page,
+ .map_sg = loongson_dma_map_sg,
+ .unmap_sg = swiotlb_unmap_sg_attrs,
+ .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+ .sync_single_for_device = loongson_dma_sync_single_for_device,
+ .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+ .sync_sg_for_device = loongson_dma_sync_sg_for_device,
+ .mapping_error = swiotlb_dma_mapping_error,
+ .dma_supported = swiotlb_dma_supported,
+ .set_dma_mask = loongson_dma_set_mask
+};
+
+void __init plat_swiotlb_setup(void)
+{
+ swiotlb_init(1);
+ mips_dma_map_ops = &loongson_dma_map_ops;
+}
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index 0a18fcf2d37..0c543eae49b 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -18,29 +18,30 @@
* option) any later version.
*/
#include <linux/module.h>
-
#include <asm/bootinfo.h>
-
#include <loongson.h>
+#include <boot_param.h>
-unsigned long cpu_clock_freq;
+u32 cpu_clock_freq;
EXPORT_SYMBOL(cpu_clock_freq);
-unsigned long memsize, highmemsize;
+struct efi_memory_map_loongson *loongson_memmap;
+struct loongson_system_configuration loongson_sysconf;
#define parse_even_earlier(res, option, p) \
do { \
unsigned int tmp __maybe_unused; \
\
if (strncmp(option, (char *)p, strlen(option)) == 0) \
- tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
+ tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
} while (0)
void __init prom_init_env(void)
{
/* pmon passes arguments in 32bit pointers */
- int *_prom_envp;
- unsigned long bus_clock;
unsigned int processor_id;
+
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
+ int *_prom_envp;
long l;
/* firmware arguments are initialized in head.S */
@@ -48,7 +49,6 @@ void __init prom_init_env(void)
l = (long)*_prom_envp;
while (l != 0) {
- parse_even_earlier(bus_clock, "busclock", l);
parse_even_earlier(cpu_clock_freq, "cpuclock", l);
parse_even_earlier(memsize, "memsize", l);
parse_even_earlier(highmemsize, "highmemsize", l);
@@ -57,8 +57,48 @@ void __init prom_init_env(void)
}
if (memsize == 0)
memsize = 256;
- if (bus_clock == 0)
- bus_clock = 66000000;
+ pr_info("memsize=%u, highmemsize=%u\n", memsize, highmemsize);
+#else
+ struct boot_params *boot_p;
+ struct loongson_params *loongson_p;
+ struct efi_cpuinfo_loongson *ecpu;
+ struct irq_source_routing_table *eirq_source;
+
+ /* firmware arguments are initialized in head.S */
+ boot_p = (struct boot_params *)fw_arg2;
+ loongson_p = &(boot_p->efi.smbios.lp);
+
+ ecpu = (struct efi_cpuinfo_loongson *)
+ ((u64)loongson_p + loongson_p->cpu_offset);
+ eirq_source = (struct irq_source_routing_table *)
+ ((u64)loongson_p + loongson_p->irq_offset);
+ loongson_memmap = (struct efi_memory_map_loongson *)
+ ((u64)loongson_p + loongson_p->memory_offset);
+
+ cpu_clock_freq = ecpu->cpu_clock_freq;
+ loongson_sysconf.cputype = ecpu->cputype;
+ loongson_sysconf.nr_cpus = ecpu->nr_cpus;
+ if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
+ loongson_sysconf.nr_cpus = NR_CPUS;
+
+ loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
+ loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
+ loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
+ loongson_sysconf.dma_mask_bits = eirq_source->dma_mask_bits;
+ if (loongson_sysconf.dma_mask_bits < 32 ||
+ loongson_sysconf.dma_mask_bits > 64)
+ loongson_sysconf.dma_mask_bits = 32;
+
+ loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
+ loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
+ loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
+
+ loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+ loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
+ pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
+ loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
+ loongson_sysconf.vgabios_addr);
+#endif
if (cpu_clock_freq == 0) {
processor_id = (&current_cpu_data)->processor_id;
switch (processor_id & PRID_REV_MASK) {
@@ -68,12 +108,13 @@ void __init prom_init_env(void)
case PRID_REV_LOONGSON2F:
cpu_clock_freq = 797000000;
break;
+ case PRID_REV_LOONGSON3A:
+ cpu_clock_freq = 900000000;
+ break;
default:
cpu_clock_freq = 100000000;
break;
}
}
-
- pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n",
- bus_clock, cpu_clock_freq, memsize, highmemsize);
+ pr_info("CpuClock = %u\n", cpu_clock_freq);
}
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index ae7af1fd5d5..f37fe5413b7 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -9,6 +9,7 @@
*/
#include <linux/bootmem.h>
+#include <asm/smp-ops.h>
#include <loongson.h>
@@ -17,10 +18,6 @@ unsigned long __maybe_unused _loongson_addrwincfg_base;
void __init prom_init(void)
{
- /* init base address of io space */
- set_io_port_base((unsigned long)
- ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
-
#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
_loongson_addrwincfg_base = (unsigned long)
ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
@@ -28,10 +25,16 @@ void __init prom_init(void)
prom_init_cmdline();
prom_init_env();
+
+ /* init base address of io space */
+ set_io_port_base((unsigned long)
+ ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
+
prom_init_memory();
/*init the uart base address */
prom_init_uart_base();
+ register_smp_ops(&loongson3_smp_ops);
}
void __init prom_free_prom_memory(void)
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c
index 4becd4f9ef2..1a4797984b8 100644
--- a/arch/mips/loongson/common/machtype.c
+++ b/arch/mips/loongson/common/machtype.c
@@ -27,6 +27,10 @@ static const char *system_types[] = {
[MACH_DEXXON_GDIUM2F10] "dexxon-gdium-2f",
[MACH_LEMOTE_NAS] "lemote-nas-2f",
[MACH_LEMOTE_LL2F] "lemote-lynloong-2f",
+ [MACH_LEMOTE_A1004] "lemote-3a-notebook-a1004",
+ [MACH_LEMOTE_A1101] "lemote-3a-itx-a1101",
+ [MACH_LEMOTE_A1201] "lemote-2gq-notebook-a1201",
+ [MACH_LEMOTE_A1205] "lemote-2gq-aio-a1205",
[MACH_LOONGSON_END] NULL,
};
diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
index 8626a42f5b9..b01d52473da 100644
--- a/arch/mips/loongson/common/mem.c
+++ b/arch/mips/loongson/common/mem.c
@@ -11,9 +11,14 @@
#include <asm/bootinfo.h>
#include <loongson.h>
+#include <boot_param.h>
#include <mem.h>
#include <pci.h>
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
+
+u32 memsize, highmemsize;
+
void __init prom_init_memory(void)
{
add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
@@ -49,6 +54,43 @@ void __init prom_init_memory(void)
#endif /* !CONFIG_64BIT */
}
+#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
+
+void __init prom_init_memory(void)
+{
+ int i;
+ u32 node_id;
+ u32 mem_type;
+
+ /* parse memory information */
+ for (i = 0; i < loongson_memmap->nr_map; i++) {
+ node_id = loongson_memmap->map[i].node_id;
+ mem_type = loongson_memmap->map[i].mem_type;
+
+ if (node_id == 0) {
+ switch (mem_type) {
+ case SYSTEM_RAM_LOW:
+ add_memory_region(loongson_memmap->map[i].mem_start,
+ (u64)loongson_memmap->map[i].mem_size << 20,
+ BOOT_MEM_RAM);
+ break;
+ case SYSTEM_RAM_HIGH:
+ add_memory_region(loongson_memmap->map[i].mem_start,
+ (u64)loongson_memmap->map[i].mem_size << 20,
+ BOOT_MEM_RAM);
+ break;
+ case MEM_RESERVED:
+ add_memory_region(loongson_memmap->map[i].mem_start,
+ (u64)loongson_memmap->map[i].mem_size << 20,
+ BOOT_MEM_RESERVED);
+ break;
+ }
+ }
+ }
+}
+
+#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
+
/* override of arch/mips/mm/cache.c: __uncached_access */
int __uncached_access(struct file *file, unsigned long addr)
{
diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
index fa778445972..003ab4e618b 100644
--- a/arch/mips/loongson/common/pci.c
+++ b/arch/mips/loongson/common/pci.c
@@ -11,6 +11,7 @@
#include <pci.h>
#include <loongson.h>
+#include <boot_param.h>
static struct resource loongson_pci_mem_resource = {
.name = "pci memory space",
@@ -82,7 +83,10 @@ static int __init pcibios_init(void)
setup_pcimap();
loongson_pci_controller.io_map_base = mips_io_port_base;
-
+#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
+ loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
+ loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
+#endif
register_pci_controller(&loongson_pci_controller);
return 0;
diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
index 65bfbb5d06f..a60715e1130 100644
--- a/arch/mips/loongson/common/reset.c
+++ b/arch/mips/loongson/common/reset.c
@@ -16,6 +16,7 @@
#include <asm/reboot.h>
#include <loongson.h>
+#include <boot_param.h>
static inline void loongson_reboot(void)
{
@@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
static void loongson_restart(char *command)
{
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
/* do preparation for reboot */
mach_prepare_reboot();
/* reboot via jumping to boot base address */
loongson_reboot();
+#else
+ void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
+
+ fw_restart();
+ while (1) {
+ if (cpu_wait)
+ cpu_wait();
+ }
+#endif
}
static void loongson_poweroff(void)
{
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
mach_prepare_shutdown();
unreachable();
+#else
+ void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
+
+ fw_poweroff();
+ while (1) {
+ if (cpu_wait)
+ cpu_wait();
+ }
+#endif
}
static void loongson_halt(void)
diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c
index 5f2b78ae97c..bd2b7095b6d 100644
--- a/arch/mips/loongson/common/serial.c
+++ b/arch/mips/loongson/common/serial.c
@@ -19,19 +19,19 @@
#include <loongson.h>
#include <machine.h>
-#define PORT(int) \
+#define PORT(int, clk) \
{ \
.irq = int, \
- .uartclk = 1843200, \
+ .uartclk = clk, \
.iotype = UPIO_PORT, \
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
.regshift = 0, \
}
-#define PORT_M(int) \
+#define PORT_M(int, clk) \
{ \
.irq = MIPS_CPU_IRQ_BASE + (int), \
- .uartclk = 3686400, \
+ .uartclk = clk, \
.iotype = UPIO_MEM, \
.membase = (void __iomem *)NULL, \
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
@@ -40,13 +40,17 @@
static struct plat_serial8250_port uart8250_data[][2] = {
[MACH_LOONGSON_UNKNOWN] {},
- [MACH_LEMOTE_FL2E] {PORT(4), {} },
- [MACH_LEMOTE_FL2F] {PORT(3), {} },
- [MACH_LEMOTE_ML2F7] {PORT_M(3), {} },
- [MACH_LEMOTE_YL2F89] {PORT_M(3), {} },
- [MACH_DEXXON_GDIUM2F10] {PORT_M(3), {} },
- [MACH_LEMOTE_NAS] {PORT_M(3), {} },
- [MACH_LEMOTE_LL2F] {PORT(3), {} },
+ [MACH_LEMOTE_FL2E] {PORT(4, 1843200), {} },
+ [MACH_LEMOTE_FL2F] {PORT(3, 1843200), {} },
+ [MACH_LEMOTE_ML2F7] {PORT_M(3, 3686400), {} },
+ [MACH_LEMOTE_YL2F89] {PORT_M(3, 3686400), {} },
+ [MACH_DEXXON_GDIUM2F10] {PORT_M(3, 3686400), {} },
+ [MACH_LEMOTE_NAS] {PORT_M(3, 3686400), {} },
+ [MACH_LEMOTE_LL2F] {PORT(3, 1843200), {} },
+ [MACH_LEMOTE_A1004] {PORT_M(2, 33177600), {} },
+ [MACH_LEMOTE_A1101] {PORT_M(2, 25000000), {} },
+ [MACH_LEMOTE_A1201] {PORT_M(2, 25000000), {} },
+ [MACH_LEMOTE_A1205] {PORT_M(2, 25000000), {} },
[MACH_LOONGSON_END] {},
};
diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson/common/setup.c
index 8223f8acfd5..bb4ac922e47 100644
--- a/arch/mips/loongson/common/setup.c
+++ b/arch/mips/loongson/common/setup.c
@@ -18,9 +18,6 @@
#include <linux/screen_info.h>
#endif
-void (*__wbflush)(void);
-EXPORT_SYMBOL(__wbflush);
-
static void wbflush_loongson(void)
{
asm(".set\tpush\n\t"
@@ -32,10 +29,11 @@ static void wbflush_loongson(void)
".set mips0\n\t");
}
+void (*__wbflush)(void) = wbflush_loongson;
+EXPORT_SYMBOL(__wbflush);
+
void __init plat_mem_setup(void)
{
- __wbflush = wbflush_loongson;
-
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c
index e192ad021ed..1e1eeea73fd 100644
--- a/arch/mips/loongson/common/uart_base.c
+++ b/arch/mips/loongson/common/uart_base.c
@@ -35,9 +35,16 @@ void prom_init_loongson_uart_base(void)
case MACH_DEXXON_GDIUM2F10:
case MACH_LEMOTE_NAS:
default:
- /* The CPU provided serial port */
+ /* The CPU provided serial port (LPC) */
loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8;
break;
+ case MACH_LEMOTE_A1004:
+ case MACH_LEMOTE_A1101:
+ case MACH_LEMOTE_A1201:
+ case MACH_LEMOTE_A1205:
+ /* The CPU provided serial port (CPU) */
+ loongson_uart_base = LOONGSON_REG_BASE + 0x1e0;
+ break;
}
_loongson_uart_base =
diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c
index 4dc2f5fa3f6..1eed38e28b1 100644
--- a/arch/mips/loongson/lemote-2f/clock.c
+++ b/arch/mips/loongson/lemote-2f/clock.c
@@ -10,7 +10,6 @@
#include <linux/cpufreq.h>
#include <linux/errno.h>
#include <linux/export.h>
-#include <linux/init.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
@@ -29,16 +28,16 @@ enum {
};
struct cpufreq_frequency_table loongson2_clockmod_table[] = {
- {DC_RESV, CPUFREQ_ENTRY_INVALID},
- {DC_ZERO, CPUFREQ_ENTRY_INVALID},
- {DC_25PT, 0},
- {DC_37PT, 0},
- {DC_50PT, 0},
- {DC_62PT, 0},
- {DC_75PT, 0},
- {DC_87PT, 0},
- {DC_DISABLE, 0},
- {DC_RESV, CPUFREQ_TABLE_END},
+ {0, DC_RESV, CPUFREQ_ENTRY_INVALID},
+ {0, DC_ZERO, CPUFREQ_ENTRY_INVALID},
+ {0, DC_25PT, 0},
+ {0, DC_37PT, 0},
+ {0, DC_50PT, 0},
+ {0, DC_62PT, 0},
+ {0, DC_75PT, 0},
+ {0, DC_87PT, 0},
+ {0, DC_DISABLE, 0},
+ {0, DC_RESV, CPUFREQ_TABLE_END},
};
EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
@@ -92,9 +91,9 @@ EXPORT_SYMBOL(clk_put);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
+ struct cpufreq_frequency_table *pos;
int ret = 0;
int regval;
- int i;
if (likely(clk->ops && clk->ops->set_rate)) {
unsigned long flags;
@@ -107,22 +106,16 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
propagate_rate(clk);
- for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
- i++) {
- if (loongson2_clockmod_table[i].frequency ==
- CPUFREQ_ENTRY_INVALID)
- continue;
- if (rate == loongson2_clockmod_table[i].frequency)
+ cpufreq_for_each_valid_entry(pos, loongson2_clockmod_table)
+ if (rate == pos->frequency)
break;
- }
- if (rate != loongson2_clockmod_table[i].frequency)
+ if (rate != pos->frequency)
return -ENOTSUPP;
clk->rate = rate;
regval = LOONGSON_CHIPCFG0;
- regval = (regval & ~0x7) |
- (loongson2_clockmod_table[i].driver_data - 1);
+ regval = (regval & ~0x7) | (pos->driver_data - 1);
LOONGSON_CHIPCFG0 = regval;
return ret;
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
new file mode 100644
index 00000000000..70152b252dd
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Loongson-3 family machines
+#
+obj-y += irq.o
+
+obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
new file mode 100644
index 00000000000..f240828181f
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/irq.c
@@ -0,0 +1,126 @@
+#include <loongson.h>
+#include <irq.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+
+unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
+
+static void ht_irqdispatch(void)
+{
+ unsigned int i, irq;
+
+ irq = LOONGSON_HT1_INT_VECTOR(0);
+ LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
+
+ for (i = 0; i < ARRAY_SIZE(ht_irq); i++) {
+ if (irq & (0x1 << ht_irq[i]))
+ do_IRQ(ht_irq[i]);
+ }
+}
+
+void mach_irq_dispatch(unsigned int pending)
+{
+ if (pending & CAUSEF_IP7)
+ do_IRQ(LOONGSON_TIMER_IRQ);
+#if defined(CONFIG_SMP)
+ else if (pending & CAUSEF_IP6)
+ loongson3_ipi_interrupt(NULL);
+#endif
+ else if (pending & CAUSEF_IP3)
+ ht_irqdispatch();
+ else if (pending & CAUSEF_IP2)
+ do_IRQ(LOONGSON_UART_IRQ);
+ else {
+ pr_err("%s : spurious interrupt\n", __func__);
+ spurious_interrupt();
+ }
+}
+
+static struct irqaction cascade_irqaction = {
+ .handler = no_action,
+ .name = "cascade",
+};
+
+static inline void mask_loongson_irq(struct irq_data *d)
+{
+ clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+ irq_disable_hazard();
+
+ /* Workaround: UART IRQ may deliver to any core */
+ if (d->irq == LOONGSON_UART_IRQ) {
+ int cpu = smp_processor_id();
+
+ LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
+ LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+ }
+}
+
+static inline void unmask_loongson_irq(struct irq_data *d)
+{
+ /* Workaround: UART IRQ may deliver to any core */
+ if (d->irq == LOONGSON_UART_IRQ) {
+ int cpu = smp_processor_id();
+
+ LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
+ LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+ }
+
+ set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+ irq_enable_hazard();
+}
+
+ /* For MIPS IRQs which shared by all cores */
+static struct irq_chip loongson_irq_chip = {
+ .name = "Loongson",
+ .irq_ack = mask_loongson_irq,
+ .irq_mask = mask_loongson_irq,
+ .irq_mask_ack = mask_loongson_irq,
+ .irq_unmask = unmask_loongson_irq,
+ .irq_eoi = unmask_loongson_irq,
+};
+
+void irq_router_init(void)
+{
+ int i;
+
+ /* route LPC int to cpu core0 int 0 */
+ LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0;
+ /* route HT1 int0 ~ int7 to cpu core0 INT1*/
+ for (i = 0; i < 8; i++)
+ LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1;
+ /* enable HT1 interrupt */
+ LOONGSON_HT1_INTN_EN(0) = 0xffffffff;
+ /* enable router interrupt intenset */
+ LOONGSON_INT_ROUTER_INTENSET =
+ LOONGSON_INT_ROUTER_INTEN | (0xffff << 16) | 0x1 << 10;
+}
+
+void __init mach_init_irq(void)
+{
+ clear_c0_status(ST0_IM | ST0_BEV);
+
+ irq_router_init();
+ mips_cpu_irq_init();
+ init_i8259_irqs();
+ irq_set_chip_and_handler(LOONGSON_UART_IRQ,
+ &loongson_irq_chip, handle_level_irq);
+
+ /* setup HT1 irq */
+ setup_irq(LOONGSON_HT1_IRQ, &cascade_irqaction);
+
+ set_c0_status(STATUSF_IP2 | STATUSF_IP6);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+void fixup_irqs(void)
+{
+ irq_cpu_offline();
+ clear_c0_status(ST0_IM);
+}
+
+#endif
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
new file mode 100644
index 00000000000..1e8894020ea
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2010, 2011, 2012, Lemote, Inc.
+ * Author: Chen Huacai, 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.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/cpufreq.h>
+#include <asm/processor.h>
+#include <asm/time.h>
+#include <asm/clock.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+#include <loongson.h>
+
+#include "smp.h"
+
+DEFINE_PER_CPU(int, cpu_state);
+DEFINE_PER_CPU(uint32_t, core0_c0count);
+
+/* read a 32bit value from ipi register */
+#define loongson3_ipi_read32(addr) readl(addr)
+/* read a 64bit value from ipi register */
+#define loongson3_ipi_read64(addr) readq(addr)
+/* write a 32bit value to ipi register */
+#define loongson3_ipi_write32(action, addr) \
+ do { \
+ writel(action, addr); \
+ __wbflush(); \
+ } while (0)
+/* write a 64bit value to ipi register */
+#define loongson3_ipi_write64(action, addr) \
+ do { \
+ writeq(action, addr); \
+ __wbflush(); \
+ } while (0)
+
+static void *ipi_set0_regs[] = {
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0),
+};
+
+static void *ipi_clear0_regs[] = {
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0),
+};
+
+static void *ipi_status0_regs[] = {
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0),
+};
+
+static void *ipi_en0_regs[] = {
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0),
+};
+
+static void *ipi_mailbox_buf[] = {
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF),
+ (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF),
+};
+
+/*
+ * Simple enough, just poke the appropriate ipi register
+ */
+static void loongson3_send_ipi_single(int cpu, unsigned int action)
+{
+ loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]);
+}
+
+static void
+loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu(i, mask)
+ loongson3_ipi_write32((u32)action, ipi_set0_regs[i]);
+}
+
+void loongson3_ipi_interrupt(struct pt_regs *regs)
+{
+ int i, cpu = smp_processor_id();
+ unsigned int action, c0count;
+
+ /* Load the ipi register to figure out what we're supposed to do */
+ action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
+
+ /* Clear the ipi register to clear the interrupt */
+ loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]);
+
+ if (action & SMP_RESCHEDULE_YOURSELF)
+ scheduler_ipi();
+
+ if (action & SMP_CALL_FUNCTION)
+ smp_call_function_interrupt();
+
+ if (action & SMP_ASK_C0COUNT) {
+ BUG_ON(cpu != 0);
+ c0count = read_c0_count();
+ for (i = 1; i < loongson_sysconf.nr_cpus; i++)
+ per_cpu(core0_c0count, i) = c0count;
+ }
+}
+
+#define MAX_LOOPS 1111
+/*
+ * SMP init and finish on secondary CPUs
+ */
+static void loongson3_init_secondary(void)
+{
+ int i;
+ uint32_t initcount;
+ unsigned int cpu = smp_processor_id();
+ unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
+ STATUSF_IP3 | STATUSF_IP2;
+
+ /* Set interrupt mask, but don't enable */
+ change_c0_status(ST0_IM, imask);
+
+ for (i = 0; i < loongson_sysconf.nr_cpus; i++)
+ loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
+
+ per_cpu(cpu_state, cpu) = CPU_ONLINE;
+
+ i = 0;
+ __get_cpu_var(core0_c0count) = 0;
+ loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
+ while (!__get_cpu_var(core0_c0count)) {
+ i++;
+ cpu_relax();
+ }
+
+ if (i > MAX_LOOPS)
+ i = MAX_LOOPS;
+ initcount = __get_cpu_var(core0_c0count) + i;
+ write_c0_count(initcount);
+}
+
+static void loongson3_smp_finish(void)
+{
+ write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
+ local_irq_enable();
+ loongson3_ipi_write64(0,
+ (void *)(ipi_mailbox_buf[smp_processor_id()]+0x0));
+ pr_info("CPU#%d finished, CP0_ST=%x\n",
+ smp_processor_id(), read_c0_status());
+}
+
+static void __init loongson3_smp_setup(void)
+{
+ int i, num;
+
+ init_cpu_possible(cpu_none_mask);
+ set_cpu_possible(0, true);
+
+ __cpu_number_map[0] = 0;
+ __cpu_logical_map[0] = 0;
+
+ /* For unified kernel, NR_CPUS is the maximum possible value,
+ * loongson_sysconf.nr_cpus is the really present value */
+ for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) {
+ set_cpu_possible(i, true);
+ __cpu_number_map[i] = ++num;
+ __cpu_logical_map[num] = i;
+ }
+ pr_info("Detected %i available secondary CPU(s)\n", num);
+}
+
+static void __init loongson3_prepare_cpus(unsigned int max_cpus)
+{
+ init_cpu_present(cpu_possible_mask);
+ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+}
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it runing!
+ */
+static void loongson3_boot_secondary(int cpu, struct task_struct *idle)
+{
+ unsigned long startargs[4];
+
+ pr_info("Booting CPU#%d...\n", cpu);
+
+ /* startargs[] are initial PC, SP and GP for secondary CPU */
+ startargs[0] = (unsigned long)&smp_bootstrap;
+ startargs[1] = (unsigned long)__KSTK_TOS(idle);
+ startargs[2] = (unsigned long)task_thread_info(idle);
+ startargs[3] = 0;
+
+ pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
+ cpu, startargs[0], startargs[1], startargs[2]);
+
+ loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18));
+ loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10));
+ loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8));
+ loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0));
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int loongson3_cpu_disable(void)
+{
+ unsigned long flags;
+ unsigned int cpu = smp_processor_id();
+
+ if (cpu == 0)
+ return -EBUSY;
+
+ set_cpu_online(cpu, false);
+ cpu_clear(cpu, cpu_callin_map);
+ local_irq_save(flags);
+ fixup_irqs();
+ local_irq_restore(flags);
+ flush_cache_all();
+ local_flush_tlb_all();
+
+ return 0;
+}
+
+
+static void loongson3_cpu_die(unsigned int cpu)
+{
+ while (per_cpu(cpu_state, cpu) != CPU_DEAD)
+ cpu_relax();
+
+ mb();
+}
+
+/* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
+ * flush all L1 entries at first. Then, another core (usually Core 0) can
+ * safely disable the clock of the target core. loongson3_play_dead() is
+ * called via CKSEG1 (uncached and unmmaped) */
+static void loongson3_play_dead(int *state_addr)
+{
+ register int val;
+ register long cpuid, core, node, count;
+ register void *addr, *base, *initfunc;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " li %[addr], 0x80000000 \n" /* KSEG0 */
+ "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
+ " cache 0, 1(%[addr]) \n"
+ " cache 0, 2(%[addr]) \n"
+ " cache 0, 3(%[addr]) \n"
+ " cache 1, 0(%[addr]) \n" /* flush L1 DCache */
+ " cache 1, 1(%[addr]) \n"
+ " cache 1, 2(%[addr]) \n"
+ " cache 1, 3(%[addr]) \n"
+ " addiu %[sets], %[sets], -1 \n"
+ " bnez %[sets], 1b \n"
+ " addiu %[addr], %[addr], 0x20 \n"
+ " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
+ " sw %[val], (%[state_addr]) \n"
+ " sync \n"
+ " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
+ " .set pop \n"
+ : [addr] "=&r" (addr), [val] "=&r" (val)
+ : [state_addr] "r" (state_addr),
+ [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " .set mips64 \n"
+ " mfc0 %[cpuid], $15, 1 \n"
+ " andi %[cpuid], 0x3ff \n"
+ " dli %[base], 0x900000003ff01000 \n"
+ " andi %[core], %[cpuid], 0x3 \n"
+ " sll %[core], 8 \n" /* get core id */
+ " or %[base], %[base], %[core] \n"
+ " andi %[node], %[cpuid], 0xc \n"
+ " dsll %[node], 42 \n" /* get node id */
+ " or %[base], %[base], %[node] \n"
+ "1: li %[count], 0x100 \n" /* wait for init loop */
+ "2: bnez %[count], 2b \n" /* limit mailbox access */
+ " addiu %[count], -1 \n"
+ " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
+ " beqz %[initfunc], 1b \n"
+ " nop \n"
+ " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
+ " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
+ " ld $a1, 0x38(%[base]) \n"
+ " jr %[initfunc] \n" /* jump to initial PC */
+ " nop \n"
+ " .set pop \n"
+ : [core] "=&r" (core), [node] "=&r" (node),
+ [base] "=&r" (base), [cpuid] "=&r" (cpuid),
+ [count] "=&r" (count), [initfunc] "=&r" (initfunc)
+ : /* No Input */
+ : "a1");
+}
+
+void play_dead(void)
+{
+ int *state_addr;
+ unsigned int cpu = smp_processor_id();
+ void (*play_dead_at_ckseg1)(int *);
+
+ idle_task_exit();
+ play_dead_at_ckseg1 =
+ (void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
+ state_addr = &per_cpu(cpu_state, cpu);
+ mb();
+ play_dead_at_ckseg1(state_addr);
+}
+
+#define CPU_POST_DEAD_FROZEN (CPU_POST_DEAD | CPU_TASKS_FROZEN)
+static int loongson3_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_POST_DEAD:
+ case CPU_POST_DEAD_FROZEN:
+ pr_info("Disable clock for CPU#%d\n", cpu);
+ LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
+ break;
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ pr_info("Enable clock for CPU#%d\n", cpu);
+ LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int register_loongson3_notifier(void)
+{
+ hotcpu_notifier(loongson3_cpu_callback, 0);
+ return 0;
+}
+early_initcall(register_loongson3_notifier);
+
+#endif
+
+struct plat_smp_ops loongson3_smp_ops = {
+ .send_ipi_single = loongson3_send_ipi_single,
+ .send_ipi_mask = loongson3_send_ipi_mask,
+ .init_secondary = loongson3_init_secondary,
+ .smp_finish = loongson3_smp_finish,
+ .boot_secondary = loongson3_boot_secondary,
+ .smp_setup = loongson3_smp_setup,
+ .prepare_cpus = loongson3_prepare_cpus,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = loongson3_cpu_disable,
+ .cpu_die = loongson3_cpu_die,
+#endif
+};
diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
new file mode 100644
index 00000000000..3453e8c4f2f
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/smp.h
@@ -0,0 +1,29 @@
+#ifndef __LOONGSON_SMP_H_
+#define __LOONGSON_SMP_H_
+
+/* for Loongson-3A smp support */
+
+/* 4 groups(nodes) in maximum in numa case */
+#define SMP_CORE_GROUP0_BASE 0x900000003ff01000
+#define SMP_CORE_GROUP1_BASE 0x900010003ff01000
+#define SMP_CORE_GROUP2_BASE 0x900020003ff01000
+#define SMP_CORE_GROUP3_BASE 0x900030003ff01000
+
+/* 4 cores in each group(node) */
+#define SMP_CORE0_OFFSET 0x000
+#define SMP_CORE1_OFFSET 0x100
+#define SMP_CORE2_OFFSET 0x200
+#define SMP_CORE3_OFFSET 0x300
+
+/* ipi registers offsets */
+#define STATUS0 0x00
+#define EN0 0x04
+#define SET0 0x08
+#define CLEAR0 0x0c
+#define STATUS1 0x10
+#define MASK1 0x14
+#define SET1 0x18
+#define CLEAR1 0x1c
+#define BUF 0x20
+
+#endif
diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig
index fbf75f63579..e23c25d0996 100644
--- a/arch/mips/loongson1/Kconfig
+++ b/arch/mips/loongson1/Kconfig
@@ -14,6 +14,7 @@ config LOONGSON1_LS1B
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM
+ select SYS_SUPPORTS_MIPS16
select SYS_HAS_EARLY_PRINTK
select COMMON_CLK
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile
index 121a848a359..619cfc1a244 100644
--- a/arch/mips/math-emu/Makefile
+++ b/arch/mips/math-emu/Makefile
@@ -2,10 +2,12 @@
# Makefile for the Linux/MIPS kernel FPU emulation.
#
-obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
- ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
- dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
- dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
- sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
- sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
- dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o
+obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o dp_div.o dp_mul.o \
+ dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \
+ dp_fint.o dp_tlong.o dp_flong.o sp_div.o sp_mul.o sp_sub.o \
+ sp_add.o sp_fdp.o sp_cmp.o sp_simple.o sp_tint.o sp_fint.o \
+ sp_tlong.o sp_flong.o dsemul.o
+
+lib-y += ieee754d.o dp_sqrt.o sp_sqrt.o
+
+obj-$(CONFIG_DEBUG_FS) += me-debugfs.o
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index efe008846ed..736c17a226e 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1,5 +1,5 @@
/*
- * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
+ * cp1emu.c: a MIPS coprocessor 1 (FPU) instruction emulator
*
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
@@ -18,61 +18,46 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* A complete emulator for MIPS coprocessor 1 instructions. This is
* required for #float(switch) or #float(trap), where it catches all
* COP1 instructions via the "CoProcessor Unusable" exception.
*
* More surprisingly it is also required for #float(ieee), to help out
- * the hardware fpu at the boundaries of the IEEE-754 representation
+ * the hardware FPU at the boundaries of the IEEE-754 representation
* (denormalised values, infinities, underflow, etc). It is made
* quite nasty because emulation of some non-COP1 instructions is
* required, e.g. in branch delay slots.
*
- * Note if you know that you won't have an fpu, then you'll get much
+ * Note if you know that you won't have an FPU, then you'll get much
* better performance by compiling with -msoft-float!
*/
#include <linux/sched.h>
-#include <linux/module.h>
#include <linux/debugfs.h>
+#include <linux/kconfig.h>
+#include <linux/percpu-defs.h>
#include <linux/perf_event.h>
+#include <asm/branch.h>
#include <asm/inst.h>
-#include <asm/bootinfo.h>
-#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
-#include <asm/mipsregs.h>
+#include <asm/uaccess.h>
+
+#include <asm/processor.h>
#include <asm/fpu_emulator.h>
#include <asm/fpu.h>
-#include <asm/uaccess.h>
-#include <asm/branch.h>
#include "ieee754.h"
-/* Strap kernel emulator for full MIPS IV emulation */
-
-#ifdef __mips
-#undef __mips
-#endif
-#define __mips 4
-
/* Function which emulates a floating point instruction. */
static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
mips_instruction);
-#if __mips >= 4 && __mips != 32
static int fpux_emu(struct pt_regs *,
struct mips_fpu_struct *, mips_instruction, void *__user *);
-#endif
-
-/* Further private data for which no space exists in mips_fpu_struct */
-
-#ifdef CONFIG_DEBUG_FS
-DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
-#endif
/* Control registers */
@@ -82,27 +67,6 @@ DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
/* Determine rounding mode from the RM bits of the FCSR */
#define modeindex(v) ((v) & FPU_CSR_RM)
-/* microMIPS bitfields */
-#define MM_POOL32A_MINOR_MASK 0x3f
-#define MM_POOL32A_MINOR_SHIFT 0x6
-#define MM_MIPS32_COND_FC 0x30
-
-/* Convert Mips rounding mode (0..3) to IEEE library modes. */
-static const unsigned char ieee_rm[4] = {
- [FPU_CSR_RN] = IEEE754_RN,
- [FPU_CSR_RZ] = IEEE754_RZ,
- [FPU_CSR_RU] = IEEE754_RU,
- [FPU_CSR_RD] = IEEE754_RD,
-};
-/* Convert IEEE library modes to Mips rounding mode (0..3). */
-static const unsigned char mips_rm[4] = {
- [IEEE754_RN] = FPU_CSR_RN,
- [IEEE754_RZ] = FPU_CSR_RZ,
- [IEEE754_RD] = FPU_CSR_RD,
- [IEEE754_RU] = FPU_CSR_RU,
-};
-
-#if __mips >= 4
/* convert condition code register number to csr bit */
static const unsigned int fpucondbit[8] = {
FPU_CSR_COND0,
@@ -114,10 +78,6 @@ static const unsigned int fpucondbit[8] = {
FPU_CSR_COND6,
FPU_CSR_COND7
};
-#endif
-
-/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
-static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};
/* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */
static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0};
@@ -417,14 +377,20 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)
case mm_mtc1_op:
case mm_cfc1_op:
case mm_ctc1_op:
+ case mm_mfhc1_op:
+ case mm_mthc1_op:
if (insn.mm_fp1_format.op == mm_mfc1_op)
op = mfc_op;
else if (insn.mm_fp1_format.op == mm_mtc1_op)
op = mtc_op;
else if (insn.mm_fp1_format.op == mm_cfc1_op)
op = cfc_op;
- else
+ else if (insn.mm_fp1_format.op == mm_ctc1_op)
op = ctc_op;
+ else if (insn.mm_fp1_format.op == mm_mfhc1_op)
+ op = mfhc_op;
+ else
+ op = mthc_op;
mips32_insn.fp1_format.opcode = cop1_op;
mips32_insn.fp1_format.op = op;
mips32_insn.fp1_format.rt =
@@ -460,199 +426,6 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)
return 0;
}
-int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
- unsigned long *contpc)
-{
- union mips_instruction insn = (union mips_instruction)dec_insn.insn;
- int bc_false = 0;
- unsigned int fcr31;
- unsigned int bit;
-
- if (!cpu_has_mmips)
- return 0;
-
- switch (insn.mm_i_format.opcode) {
- case mm_pool32a_op:
- if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) ==
- mm_pool32axf_op) {
- switch (insn.mm_i_format.simmediate >>
- MM_POOL32A_MINOR_SHIFT) {
- case mm_jalr_op:
- case mm_jalrhb_op:
- case mm_jalrs_op:
- case mm_jalrshb_op:
- if (insn.mm_i_format.rt != 0) /* Not mm_jr */
- regs->regs[insn.mm_i_format.rt] =
- regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- *contpc = regs->regs[insn.mm_i_format.rs];
- return 1;
- }
- }
- break;
- case mm_pool32i_op:
- switch (insn.mm_i_format.rt) {
- case mm_bltzals_op:
- case mm_bltzal_op:
- regs->regs[31] = regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- /* Fall through */
- case mm_bltz_op:
- if ((long)regs->regs[insn.mm_i_format.rs] < 0)
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_i_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- return 1;
- case mm_bgezals_op:
- case mm_bgezal_op:
- regs->regs[31] = regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- /* Fall through */
- case mm_bgez_op:
- if ((long)regs->regs[insn.mm_i_format.rs] >= 0)
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_i_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- return 1;
- case mm_blez_op:
- if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_i_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- return 1;
- case mm_bgtz_op:
- if ((long)regs->regs[insn.mm_i_format.rs] <= 0)
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_i_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- return 1;
- case mm_bc2f_op:
- case mm_bc1f_op:
- bc_false = 1;
- /* Fall through */
- case mm_bc2t_op:
- case mm_bc1t_op:
- preempt_disable();
- if (is_fpu_owner())
- asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
- else
- fcr31 = current->thread.fpu.fcr31;
- preempt_enable();
-
- if (bc_false)
- fcr31 = ~fcr31;
-
- bit = (insn.mm_i_format.rs >> 2);
- bit += (bit != 0);
- bit += 23;
- if (fcr31 & (1 << bit))
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_i_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc + dec_insn.next_pc_inc;
- return 1;
- }
- break;
- case mm_pool16c_op:
- switch (insn.mm_i_format.rt) {
- case mm_jalr16_op:
- case mm_jalrs16_op:
- regs->regs[31] = regs->cp0_epc +
- dec_insn.pc_inc + dec_insn.next_pc_inc;
- /* Fall through */
- case mm_jr16_op:
- *contpc = regs->regs[insn.mm_i_format.rs];
- return 1;
- }
- break;
- case mm_beqz16_op:
- if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0)
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_b1_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc + dec_insn.next_pc_inc;
- return 1;
- case mm_bnez16_op:
- if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0)
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_b1_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc + dec_insn.next_pc_inc;
- return 1;
- case mm_b16_op:
- *contpc = regs->cp0_epc + dec_insn.pc_inc +
- (insn.mm_b0_format.simmediate << 1);
- return 1;
- case mm_beq32_op:
- if (regs->regs[insn.mm_i_format.rs] ==
- regs->regs[insn.mm_i_format.rt])
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_i_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- dec_insn.next_pc_inc;
- return 1;
- case mm_bne32_op:
- if (regs->regs[insn.mm_i_format.rs] !=
- regs->regs[insn.mm_i_format.rt])
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc +
- (insn.mm_i_format.simmediate << 1);
- else
- *contpc = regs->cp0_epc +
- dec_insn.pc_inc + dec_insn.next_pc_inc;
- return 1;
- case mm_jalx32_op:
- regs->regs[31] = regs->cp0_epc +
- dec_insn.pc_inc + dec_insn.next_pc_inc;
- *contpc = regs->cp0_epc + dec_insn.pc_inc;
- *contpc >>= 28;
- *contpc <<= 28;
- *contpc |= (insn.j_format.target << 2);
- return 1;
- case mm_jals32_op:
- case mm_jal32_op:
- regs->regs[31] = regs->cp0_epc +
- dec_insn.pc_inc + dec_insn.next_pc_inc;
- /* Fall through */
- case mm_j32_op:
- *contpc = regs->cp0_epc + dec_insn.pc_inc;
- *contpc >>= 27;
- *contpc <<= 27;
- *contpc |= (insn.j_format.target << 1);
- set_isa16_mode(*contpc);
- return 1;
- }
- return 0;
-}
-
/*
* Redundant with logic already in kernel/branch.c,
* embedded in compute_return_epc. At some point,
@@ -811,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
if (insn.i_format.rs == bc_op) {
preempt_disable();
if (is_fpu_owner())
- asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+ asm volatile(
+ ".set push\n"
+ "\t.set mips1\n"
+ "\tcfc1\t%0,$31\n"
+ "\t.set pop" : "=r" (fcr31));
else
fcr31 = current->thread.fpu.fcr31;
preempt_enable();
@@ -853,33 +630,64 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
* In the Linux kernel, we support selection of FPR format on the
* basis of the Status.FR bit. If an FPU is not present, the FR bit
* is hardwired to zero, which would imply a 32-bit FPU even for
- * 64-bit CPUs so we rather look at TIF_32BIT_REGS.
+ * 64-bit CPUs so we rather look at TIF_32BIT_FPREGS.
* FPU emu is slow and bulky and optimizing this function offers fairly
* sizeable benefits so we try to be clever and make this function return
* a constant whenever possible, that is on 64-bit kernels without O32
- * compatibility enabled and on 32-bit kernels.
+ * compatibility enabled and on 32-bit without 64-bit FPU support.
*/
static inline int cop1_64bit(struct pt_regs *xcp)
{
-#if defined(CONFIG_64BIT) && !defined(CONFIG_MIPS32_O32)
- return 1;
-#elif defined(CONFIG_64BIT) && defined(CONFIG_MIPS32_O32)
- return !test_thread_flag(TIF_32BIT_REGS);
-#else
- return 0;
-#endif
-}
-
-#define SIFROMREG(si, x) ((si) = cop1_64bit(xcp) || !(x & 1) ? \
- (int)ctx->fpr[x] : (int)(ctx->fpr[x & ~1] >> 32))
+ if (config_enabled(CONFIG_64BIT) && !config_enabled(CONFIG_MIPS32_O32))
+ return 1;
+ else if (config_enabled(CONFIG_32BIT) &&
+ !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
+ return 0;
-#define SITOREG(si, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = \
- cop1_64bit(xcp) || !(x & 1) ? \
- ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \
- ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32)
+ return !test_thread_flag(TIF_32BIT_FPREGS);
+}
-#define DIFROMREG(di, x) ((di) = ctx->fpr[x & ~(cop1_64bit(xcp) == 0)])
-#define DITOREG(di, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = (di))
+#define SIFROMREG(si, x) \
+do { \
+ if (cop1_64bit(xcp)) \
+ (si) = get_fpr32(&ctx->fpr[x], 0); \
+ else \
+ (si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \
+} while (0)
+
+#define SITOREG(si, x) \
+do { \
+ if (cop1_64bit(xcp)) { \
+ unsigned i; \
+ set_fpr32(&ctx->fpr[x], 0, si); \
+ for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
+ set_fpr32(&ctx->fpr[x], i, 0); \
+ } else { \
+ set_fpr32(&ctx->fpr[(x) & ~1], (x) & 1, si); \
+ } \
+} while (0)
+
+#define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1))
+
+#define SITOHREG(si, x) \
+do { \
+ unsigned i; \
+ set_fpr32(&ctx->fpr[x], 1, si); \
+ for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \
+ set_fpr32(&ctx->fpr[x], i, 0); \
+} while (0)
+
+#define DIFROMREG(di, x) \
+ ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0))
+
+#define DITOREG(di, x) \
+do { \
+ unsigned fpr, i; \
+ fpr = (x) & ~(cop1_64bit(xcp) == 0); \
+ set_fpr64(&ctx->fpr[fpr], 0, di); \
+ for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++) \
+ set_fpr64(&ctx->fpr[fpr], i, 0); \
+} while (0)
#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
#define SPTOREG(sp, x) SITOREG((sp).bits, x)
@@ -894,23 +702,36 @@ static inline int cop1_64bit(struct pt_regs *xcp)
static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
struct mm_decoded_insn dec_insn, void *__user *fault_addr)
{
- mips_instruction ir;
unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc;
- unsigned int cond;
- int pc_inc;
+ unsigned int cond, cbit;
+ mips_instruction ir;
+ int likely, pc_inc;
+ u32 __user *wva;
+ u64 __user *dva;
+ u32 value;
+ u32 wval;
+ u64 dval;
+ int sig;
+
+ /*
+ * These are giving gcc a gentle hint about what to expect in
+ * dec_inst in order to do better optimization.
+ */
+ if (!cpu_has_mmips && dec_insn.micro_mips_mode)
+ unreachable();
/* XXX NEC Vr54xx bug workaround */
- if (xcp->cp0_cause & CAUSEF_BD) {
+ if (delay_slot(xcp)) {
if (dec_insn.micro_mips_mode) {
if (!mm_isBranchInstr(xcp, dec_insn, &contpc))
- xcp->cp0_cause &= ~CAUSEF_BD;
+ clear_delay_slot(xcp);
} else {
if (!isBranchInstr(xcp, dec_insn, &contpc))
- xcp->cp0_cause &= ~CAUSEF_BD;
+ clear_delay_slot(xcp);
}
}
- if (xcp->cp0_cause & CAUSEF_BD) {
+ if (delay_slot(xcp)) {
/*
* The instruction to be emulated is in a branch delay slot
* which means that we have to emulate the branch instruction
@@ -952,96 +773,85 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return SIGILL;
}
- emul:
+emul:
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0);
MIPS_FPU_EMU_INC_STATS(emulated);
switch (MIPSInst_OPCODE(ir)) {
- case ldc1_op:{
- u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
- MIPSInst_SIMM(ir));
- u64 val;
-
+ case ldc1_op:
+ dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
MIPS_FPU_EMU_INC_STATS(loads);
- if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
+ if (!access_ok(VERIFY_READ, dva, sizeof(u64))) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = dva;
return SIGBUS;
}
- if (__get_user(val, va)) {
+ if (__get_user(dval, dva)) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = dva;
return SIGSEGV;
}
- DITOREG(val, MIPSInst_RT(ir));
+ DITOREG(dval, MIPSInst_RT(ir));
break;
- }
-
- case sdc1_op:{
- u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
- MIPSInst_SIMM(ir));
- u64 val;
+ case sdc1_op:
+ dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
MIPS_FPU_EMU_INC_STATS(stores);
- DIFROMREG(val, MIPSInst_RT(ir));
- if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
+ DIFROMREG(dval, MIPSInst_RT(ir));
+ if (!access_ok(VERIFY_WRITE, dva, sizeof(u64))) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = dva;
return SIGBUS;
}
- if (__put_user(val, va)) {
+ if (__put_user(dval, dva)) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = dva;
return SIGSEGV;
}
break;
- }
-
- case lwc1_op:{
- u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
- MIPSInst_SIMM(ir));
- u32 val;
+ case lwc1_op:
+ wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
MIPS_FPU_EMU_INC_STATS(loads);
- if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
+ if (!access_ok(VERIFY_READ, wva, sizeof(u32))) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = wva;
return SIGBUS;
}
- if (__get_user(val, va)) {
+ if (__get_user(wval, wva)) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = wva;
return SIGSEGV;
}
- SITOREG(val, MIPSInst_RT(ir));
+ SITOREG(wval, MIPSInst_RT(ir));
break;
- }
-
- case swc1_op:{
- u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
- MIPSInst_SIMM(ir));
- u32 val;
+ case swc1_op:
+ wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
MIPS_FPU_EMU_INC_STATS(stores);
- SIFROMREG(val, MIPSInst_RT(ir));
- if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
+ SIFROMREG(wval, MIPSInst_RT(ir));
+ if (!access_ok(VERIFY_WRITE, wva, sizeof(u32))) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = wva;
return SIGBUS;
}
- if (__put_user(val, va)) {
+ if (__put_user(wval, wva)) {
MIPS_FPU_EMU_INC_STATS(errors);
- *fault_addr = va;
+ *fault_addr = wva;
return SIGSEGV;
}
break;
- }
case cop1_op:
switch (MIPSInst_RS(ir)) {
-
-#if defined(__mips64)
case dmfc_op:
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
+
/* copregister fs -> gpr[rt] */
if (MIPSInst_RT(ir) != 0) {
DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
@@ -1050,10 +860,31 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
break;
case dmtc_op:
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
+
/* copregister fs <- rt */
DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
break;
-#endif
+
+ case mfhc_op:
+ if (!cpu_has_mips_r2)
+ goto sigill;
+
+ /* copregister rd -> gpr[rt] */
+ if (MIPSInst_RT(ir) != 0) {
+ SIFROMHREG(xcp->regs[MIPSInst_RT(ir)],
+ MIPSInst_RD(ir));
+ }
+ break;
+
+ case mthc_op:
+ if (!cpu_has_mips_r2)
+ goto sigill;
+
+ /* copregister rd <- gpr[rt] */
+ SITOHREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
+ break;
case mfc_op:
/* copregister rd -> gpr[rt] */
@@ -1068,19 +899,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
break;
- case cfc_op:{
+ case cfc_op:
/* cop control register rd -> gpr[rt] */
- u32 value;
-
if (MIPSInst_RD(ir) == FPCREG_CSR) {
value = ctx->fcr31;
- value = (value & ~FPU_CSR_RM) |
- mips_rm[modeindex(value)];
-#ifdef CSRTRACE
- printk("%p gpr[%d]<-csr=%08x\n",
- (void *) (xcp->cp0_epc),
- MIPSInst_RT(ir), value);
-#endif
+ value = (value & ~FPU_CSR_RM) | modeindex(value);
+ pr_debug("%p gpr[%d]<-csr=%08x\n",
+ (void *) (xcp->cp0_epc),
+ MIPSInst_RT(ir), value);
}
else if (MIPSInst_RD(ir) == FPCREG_RID)
value = 0;
@@ -1089,12 +915,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
if (MIPSInst_RT(ir))
xcp->regs[MIPSInst_RT(ir)] = value;
break;
- }
- case ctc_op:{
+ case ctc_op:
/* copregister rd <- rt */
- u32 value;
-
if (MIPSInst_RT(ir) == 0)
value = 0;
else
@@ -1103,37 +926,33 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
/* we only have one writable control reg
*/
if (MIPSInst_RD(ir) == FPCREG_CSR) {
-#ifdef CSRTRACE
- printk("%p gpr[%d]->csr=%08x\n",
- (void *) (xcp->cp0_epc),
- MIPSInst_RT(ir), value);
-#endif
+ pr_debug("%p gpr[%d]->csr=%08x\n",
+ (void *) (xcp->cp0_epc),
+ MIPSInst_RT(ir), value);
/*
* Don't write reserved bits,
* and convert to ieee library modes
*/
- ctx->fcr31 = (value &
- ~(FPU_CSR_RSVD | FPU_CSR_RM)) |
- ieee_rm[modeindex(value)];
+ ctx->fcr31 = (value & ~(FPU_CSR_RSVD | FPU_CSR_RM)) |
+ modeindex(value);
}
if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
return SIGFPE;
}
break;
- }
-
- case bc_op:{
- int likely = 0;
- if (xcp->cp0_cause & CAUSEF_BD)
+ case bc_op:
+ if (delay_slot(xcp))
return SIGILL;
-#if __mips >= 4
- cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2];
-#else
- cond = ctx->fcr31 & FPU_CSR_COND;
-#endif
+ if (cpu_has_mips_4_5_r)
+ cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
+ else
+ cbit = FPU_CSR_COND;
+ cond = ctx->fcr31 & cbit;
+
+ likely = 0;
switch (MIPSInst_RT(ir) & 3) {
case bcfl_op:
likely = 1;
@@ -1149,10 +968,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return SIGILL;
}
- xcp->cp0_cause |= CAUSEF_BD;
+ set_delay_slot(xcp);
if (cond) {
- /* branch taken: emulate dslot
- * instruction
+ /*
+ * Branch taken: emulate dslot instruction
*/
xcp->cp0_epc += dec_insn.pc_inc;
@@ -1186,23 +1005,37 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
switch (MIPSInst_OPCODE(ir)) {
case lwc1_op:
+ goto emul;
+
case swc1_op:
-#if (__mips >= 2 || defined(__mips64))
+ goto emul;
+
case ldc1_op:
case sdc1_op:
-#endif
+ if (cpu_has_mips_2_3_4_5 ||
+ cpu_has_mips64)
+ goto emul;
+
+ return SIGILL;
+ goto emul;
+
case cop1_op:
-#if __mips >= 4 && __mips != 32
- case cop1x_op:
-#endif
- /* its one of ours */
goto emul;
-#if __mips >= 4
+
+ case cop1x_op:
+ if (cpu_has_mips_4_5 || cpu_has_mips64)
+ /* its one of ours */
+ goto emul;
+
+ return SIGILL;
+
case spec_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
if (MIPSInst_FUNC(ir) == movc_op)
goto emul;
break;
-#endif
}
/*
@@ -1210,10 +1043,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
* instruction in the dslot
*/
return mips_dsemul(xcp, ir, contpc);
- }
- else {
- /* branch not taken */
- if (likely) {
+ } else if (likely) { /* branch not taken */
/*
* branch likely nullifies
* dslot if not taken
@@ -1225,34 +1055,31 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
* dslot as normal insn
*/
}
- }
break;
- }
default:
if (!(MIPSInst_RS(ir) & 0x10))
return SIGILL;
- {
- int sig;
- /* a real fpu computation instruction */
- if ((sig = fpu_emu(xcp, ctx, ir)))
- return sig;
- }
+ /* a real fpu computation instruction */
+ if ((sig = fpu_emu(xcp, ctx, ir)))
+ return sig;
}
break;
-#if __mips >= 4 && __mips != 32
- case cop1x_op:{
- int sig = fpux_emu(xcp, ctx, ir, fault_addr);
+ case cop1x_op:
+ if (!cpu_has_mips_4_5 && !cpu_has_mips64)
+ return SIGILL;
+
+ sig = fpux_emu(xcp, ctx, ir, fault_addr);
if (sig)
return sig;
break;
- }
-#endif
-#if __mips >= 4
case spec_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
if (MIPSInst_FUNC(ir) != movc_op)
return SIGILL;
cond = fpucondbit[MIPSInst_RT(ir) >> 2];
@@ -1260,15 +1087,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
xcp->regs[MIPSInst_RD(ir)] =
xcp->regs[MIPSInst_RS(ir)];
break;
-#endif
-
default:
+sigill:
return SIGILL;
}
/* we did it !! */
xcp->cp0_epc = contpc;
- xcp->cp0_cause &= ~CAUSEF_BD;
+ clear_delay_slot(xcp);
return 0;
}
@@ -1289,44 +1115,42 @@ static const unsigned char cmptab[8] = {
};
-#if __mips >= 4 && __mips != 32
-
/*
* Additional MIPS4 instructions
*/
-#define DEF3OP(name, p, f1, f2, f3) \
-static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \
- ieee754##p t) \
-{ \
- struct _ieee754_csr ieee754_csr_save; \
- s = f1(s, t); \
- ieee754_csr_save = ieee754_csr; \
- s = f2(s, r); \
- ieee754_csr_save.cx |= ieee754_csr.cx; \
- ieee754_csr_save.sx |= ieee754_csr.sx; \
- s = f3(s); \
- ieee754_csr.cx |= ieee754_csr_save.cx; \
- ieee754_csr.sx |= ieee754_csr_save.sx; \
- return s; \
+#define DEF3OP(name, p, f1, f2, f3) \
+static union ieee754##p fpemu_##p##_##name(union ieee754##p r, \
+ union ieee754##p s, union ieee754##p t) \
+{ \
+ struct _ieee754_csr ieee754_csr_save; \
+ s = f1(s, t); \
+ ieee754_csr_save = ieee754_csr; \
+ s = f2(s, r); \
+ ieee754_csr_save.cx |= ieee754_csr.cx; \
+ ieee754_csr_save.sx |= ieee754_csr.sx; \
+ s = f3(s); \
+ ieee754_csr.cx |= ieee754_csr_save.cx; \
+ ieee754_csr.sx |= ieee754_csr_save.sx; \
+ return s; \
}
-static ieee754dp fpemu_dp_recip(ieee754dp d)
+static union ieee754dp fpemu_dp_recip(union ieee754dp d)
{
return ieee754dp_div(ieee754dp_one(0), d);
}
-static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+static union ieee754dp fpemu_dp_rsqrt(union ieee754dp d)
{
return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
}
-static ieee754sp fpemu_sp_recip(ieee754sp s)
+static union ieee754sp fpemu_sp_recip(union ieee754sp s)
{
return ieee754sp_div(ieee754sp_one(0), s);
}
-static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+static union ieee754sp fpemu_sp_rsqrt(union ieee754sp s)
{
return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
}
@@ -1350,8 +1174,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
switch (MIPSInst_FMA_FFMT(ir)) {
case s_fmt:{ /* 0 */
- ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
- ieee754sp fd, fr, fs, ft;
+ union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp);
+ union ieee754sp fd, fr, fs, ft;
u32 __user *va;
u32 val;
@@ -1414,18 +1238,26 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
SPTOREG(fd, MIPSInst_FD(ir));
copcsr:
- if (ieee754_cxtest(IEEE754_INEXACT))
+ if (ieee754_cxtest(IEEE754_INEXACT)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_inexact);
rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
- if (ieee754_cxtest(IEEE754_UNDERFLOW))
+ }
+ if (ieee754_cxtest(IEEE754_UNDERFLOW)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_underflow);
rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
- if (ieee754_cxtest(IEEE754_OVERFLOW))
+ }
+ if (ieee754_cxtest(IEEE754_OVERFLOW)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_overflow);
rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
- if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ }
+ if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);
rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
+ }
ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
- /*printk ("SIGFPE: fpu csr = %08x\n",
+ /*printk ("SIGFPE: FPU csr = %08x\n",
ctx->fcr31); */
return SIGFPE;
}
@@ -1439,8 +1271,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
}
case d_fmt:{ /* 1 */
- ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
- ieee754dp fd, fr, fs, ft;
+ union ieee754dp(*handler) (union ieee754dp, union ieee754dp, union ieee754dp);
+ union ieee754dp fd, fr, fs, ft;
u64 __user *va;
u64 val;
@@ -1508,10 +1340,10 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
break;
}
- case 0x7: /* 7 */
- if (MIPSInst_FUNC(ir) != pfetch_op) {
+ case 0x3:
+ if (MIPSInst_FUNC(ir) != pfetch_op)
return SIGILL;
- }
+
/* ignore prefx operation */
break;
@@ -1521,7 +1353,6 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return 0;
}
-#endif
@@ -1533,23 +1364,25 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
{
int rfmt; /* resulting format */
unsigned rcsr = 0; /* resulting csr */
+ unsigned int oldrm;
+ unsigned int cbit;
unsigned cond;
union {
- ieee754dp d;
- ieee754sp s;
+ union ieee754dp d;
+ union ieee754sp s;
int w;
-#ifdef __mips64
s64 l;
-#endif
} rv; /* resulting value */
+ u64 bits;
MIPS_FPU_EMU_INC_STATS(cp1ops);
switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
- case s_fmt:{ /* 0 */
+ case s_fmt: { /* 0 */
union {
- ieee754sp(*b) (ieee754sp, ieee754sp);
- ieee754sp(*u) (ieee754sp);
+ union ieee754sp(*b) (union ieee754sp, union ieee754sp);
+ union ieee754sp(*u) (union ieee754sp);
} handler;
+ union ieee754sp fs, ft;
switch (MIPSInst_FUNC(ir)) {
/* binary ops */
@@ -1567,148 +1400,167 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
goto scopbop;
/* unary ops */
-#if __mips >= 2 || defined(__mips64)
case fsqrt_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
handler.u = ieee754sp_sqrt;
goto scopuop;
-#endif
-#if __mips >= 4 && __mips != 32
+
+ /*
+ * Note that on some MIPS IV implementations such as the
+ * R5000 and R8000 the FSQRT and FRECIP instructions do not
+ * achieve full IEEE-754 accuracy - however this emulator does.
+ */
case frsqrt_op:
+ if (!cpu_has_mips_4_5_r2)
+ return SIGILL;
+
handler.u = fpemu_sp_rsqrt;
goto scopuop;
+
case frecip_op:
+ if (!cpu_has_mips_4_5_r2)
+ return SIGILL;
+
handler.u = fpemu_sp_recip;
goto scopuop;
-#endif
-#if __mips >= 4
+
case fmovc_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
cond = fpucondbit[MIPSInst_FT(ir) >> 2];
if (((ctx->fcr31 & cond) != 0) !=
((MIPSInst_FT(ir) & 1) != 0))
return 0;
SPFROMREG(rv.s, MIPSInst_FS(ir));
break;
+
case fmovz_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
if (xcp->regs[MIPSInst_FT(ir)] != 0)
return 0;
SPFROMREG(rv.s, MIPSInst_FS(ir));
break;
+
case fmovn_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
if (xcp->regs[MIPSInst_FT(ir)] == 0)
return 0;
SPFROMREG(rv.s, MIPSInst_FS(ir));
break;
-#endif
+
case fabs_op:
handler.u = ieee754sp_abs;
goto scopuop;
+
case fneg_op:
handler.u = ieee754sp_neg;
goto scopuop;
+
case fmov_op:
/* an easy one */
SPFROMREG(rv.s, MIPSInst_FS(ir));
goto copcsr;
/* binary op on handler */
- scopbop:
- {
- ieee754sp fs, ft;
-
- SPFROMREG(fs, MIPSInst_FS(ir));
- SPFROMREG(ft, MIPSInst_FT(ir));
-
- rv.s = (*handler.b) (fs, ft);
- goto copcsr;
- }
- scopuop:
- {
- ieee754sp fs;
+scopbop:
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
- SPFROMREG(fs, MIPSInst_FS(ir));
- rv.s = (*handler.u) (fs);
- goto copcsr;
- }
- copcsr:
- if (ieee754_cxtest(IEEE754_INEXACT))
+ rv.s = (*handler.b) (fs, ft);
+ goto copcsr;
+scopuop:
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = (*handler.u) (fs);
+ goto copcsr;
+copcsr:
+ if (ieee754_cxtest(IEEE754_INEXACT)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_inexact);
rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
- if (ieee754_cxtest(IEEE754_UNDERFLOW))
+ }
+ if (ieee754_cxtest(IEEE754_UNDERFLOW)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_underflow);
rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
- if (ieee754_cxtest(IEEE754_OVERFLOW))
+ }
+ if (ieee754_cxtest(IEEE754_OVERFLOW)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_overflow);
rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
- if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
+ }
+ if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_zerodiv);
rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
- if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ }
+ if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) {
+ MIPS_FPU_EMU_INC_STATS(ieee754_invalidop);
rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
+ }
break;
/* unary conv ops */
case fcvts_op:
return SIGILL; /* not defined */
- case fcvtd_op:{
- ieee754sp fs;
+ case fcvtd_op:
SPFROMREG(fs, MIPSInst_FS(ir));
rv.d = ieee754dp_fsp(fs);
rfmt = d_fmt;
goto copcsr;
- }
- case fcvtw_op:{
- ieee754sp fs;
+ case fcvtw_op:
SPFROMREG(fs, MIPSInst_FS(ir));
rv.w = ieee754sp_tint(fs);
rfmt = w_fmt;
goto copcsr;
- }
-#if __mips >= 2 || defined(__mips64)
case fround_op:
case ftrunc_op:
case fceil_op:
- case ffloor_op:{
- unsigned int oldrm = ieee754_csr.rm;
- ieee754sp fs;
+ case ffloor_op:
+ if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
+ oldrm = ieee754_csr.rm;
SPFROMREG(fs, MIPSInst_FS(ir));
- ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
+ ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
rv.w = ieee754sp_tint(fs);
ieee754_csr.rm = oldrm;
rfmt = w_fmt;
goto copcsr;
- }
-#endif /* __mips >= 2 */
-#if defined(__mips64)
- case fcvtl_op:{
- ieee754sp fs;
+ case fcvtl_op:
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
SPFROMREG(fs, MIPSInst_FS(ir));
rv.l = ieee754sp_tlong(fs);
rfmt = l_fmt;
goto copcsr;
- }
case froundl_op:
case ftruncl_op:
case fceill_op:
- case ffloorl_op:{
- unsigned int oldrm = ieee754_csr.rm;
- ieee754sp fs;
+ case ffloorl_op:
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
+ oldrm = ieee754_csr.rm;
SPFROMREG(fs, MIPSInst_FS(ir));
- ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
+ ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
rv.l = ieee754sp_tlong(fs);
ieee754_csr.rm = oldrm;
rfmt = l_fmt;
goto copcsr;
- }
-#endif /* defined(__mips64) */
default:
if (MIPSInst_FUNC(ir) >= fcmp_op) {
unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
- ieee754sp fs, ft;
+ union ieee754sp fs, ft;
SPFROMREG(fs, MIPSInst_FS(ir));
SPFROMREG(ft, MIPSInst_FT(ir));
@@ -1721,19 +1573,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
else
goto copcsr;
- }
- else {
+ } else
return SIGILL;
- }
break;
}
break;
}
- case d_fmt:{
+ case d_fmt: {
+ union ieee754dp fs, ft;
union {
- ieee754dp(*b) (ieee754dp, ieee754dp);
- ieee754dp(*u) (ieee754dp);
+ union ieee754dp(*b) (union ieee754dp, union ieee754dp);
+ union ieee754dp(*u) (union ieee754dp);
} handler;
switch (MIPSInst_FUNC(ir)) {
@@ -1752,21 +1603,33 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
goto dcopbop;
/* unary ops */
-#if __mips >= 2 || defined(__mips64)
case fsqrt_op:
+ if (!cpu_has_mips_2_3_4_5_r)
+ return SIGILL;
+
handler.u = ieee754dp_sqrt;
goto dcopuop;
-#endif
-#if __mips >= 4 && __mips != 32
+ /*
+ * Note that on some MIPS IV implementations such as the
+ * R5000 and R8000 the FSQRT and FRECIP instructions do not
+ * achieve full IEEE-754 accuracy - however this emulator does.
+ */
case frsqrt_op:
+ if (!cpu_has_mips_4_5_r2)
+ return SIGILL;
+
handler.u = fpemu_dp_rsqrt;
goto dcopuop;
case frecip_op:
+ if (!cpu_has_mips_4_5_r2)
+ return SIGILL;
+
handler.u = fpemu_dp_recip;
goto dcopuop;
-#endif
-#if __mips >= 4
case fmovc_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
cond = fpucondbit[MIPSInst_FT(ir) >> 2];
if (((ctx->fcr31 & cond) != 0) !=
((MIPSInst_FT(ir) & 1) != 0))
@@ -1774,16 +1637,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
DPFROMREG(rv.d, MIPSInst_FS(ir));
break;
case fmovz_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
if (xcp->regs[MIPSInst_FT(ir)] != 0)
return 0;
DPFROMREG(rv.d, MIPSInst_FS(ir));
break;
case fmovn_op:
+ if (!cpu_has_mips_4_5_r)
+ return SIGILL;
+
if (xcp->regs[MIPSInst_FT(ir)] == 0)
return 0;
DPFROMREG(rv.d, MIPSInst_FS(ir));
break;
-#endif
case fabs_op:
handler.u = ieee754dp_abs;
goto dcopuop;
@@ -1798,91 +1666,78 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
goto copcsr;
/* binary op on handler */
- dcopbop:{
- ieee754dp fs, ft;
-
- DPFROMREG(fs, MIPSInst_FS(ir));
- DPFROMREG(ft, MIPSInst_FT(ir));
-
- rv.d = (*handler.b) (fs, ft);
- goto copcsr;
- }
- dcopuop:{
- ieee754dp fs;
-
- DPFROMREG(fs, MIPSInst_FS(ir));
- rv.d = (*handler.u) (fs);
- goto copcsr;
- }
+dcopbop:
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
- /* unary conv ops */
- case fcvts_op:{
- ieee754dp fs;
+ rv.d = (*handler.b) (fs, ft);
+ goto copcsr;
+dcopuop:
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = (*handler.u) (fs);
+ goto copcsr;
+ /*
+ * unary conv ops
+ */
+ case fcvts_op:
DPFROMREG(fs, MIPSInst_FS(ir));
rv.s = ieee754sp_fdp(fs);
rfmt = s_fmt;
goto copcsr;
- }
+
case fcvtd_op:
return SIGILL; /* not defined */
- case fcvtw_op:{
- ieee754dp fs;
-
+ case fcvtw_op:
DPFROMREG(fs, MIPSInst_FS(ir));
rv.w = ieee754dp_tint(fs); /* wrong */
rfmt = w_fmt;
goto copcsr;
- }
-#if __mips >= 2 || defined(__mips64)
case fround_op:
case ftrunc_op:
case fceil_op:
- case ffloor_op:{
- unsigned int oldrm = ieee754_csr.rm;
- ieee754dp fs;
+ case ffloor_op:
+ if (!cpu_has_mips_2_3_4_5_r)
+ return SIGILL;
+ oldrm = ieee754_csr.rm;
DPFROMREG(fs, MIPSInst_FS(ir));
- ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
+ ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
rv.w = ieee754dp_tint(fs);
ieee754_csr.rm = oldrm;
rfmt = w_fmt;
goto copcsr;
- }
-#endif
-#if defined(__mips64)
- case fcvtl_op:{
- ieee754dp fs;
+ case fcvtl_op:
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
DPFROMREG(fs, MIPSInst_FS(ir));
rv.l = ieee754dp_tlong(fs);
rfmt = l_fmt;
goto copcsr;
- }
case froundl_op:
case ftruncl_op:
case fceill_op:
- case ffloorl_op:{
- unsigned int oldrm = ieee754_csr.rm;
- ieee754dp fs;
+ case ffloorl_op:
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
+ oldrm = ieee754_csr.rm;
DPFROMREG(fs, MIPSInst_FS(ir));
- ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
+ ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
rv.l = ieee754dp_tlong(fs);
ieee754_csr.rm = oldrm;
rfmt = l_fmt;
goto copcsr;
- }
-#endif /* __mips >= 3 */
default:
if (MIPSInst_FUNC(ir) >= fcmp_op) {
unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
- ieee754dp fs, ft;
+ union ieee754dp fs, ft;
DPFROMREG(fs, MIPSInst_FS(ir));
DPFROMREG(ft, MIPSInst_FT(ir));
@@ -1904,11 +1759,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
break;
}
break;
- }
-
- case w_fmt:{
- ieee754sp fs;
+ case w_fmt:
switch (MIPSInst_FUNC(ir)) {
case fcvts_op:
/* convert word to single precision real */
@@ -1928,25 +1780,28 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
break;
}
-#if defined(__mips64)
- case l_fmt:{
+ case l_fmt:
+
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
+
+ DIFROMREG(bits, MIPSInst_FS(ir));
+
switch (MIPSInst_FUNC(ir)) {
case fcvts_op:
/* convert long to single precision real */
- rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]);
+ rv.s = ieee754sp_flong(bits);
rfmt = s_fmt;
goto copcsr;
case fcvtd_op:
/* convert long to double precision real */
- rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]);
+ rv.d = ieee754dp_flong(bits);
rfmt = d_fmt;
goto copcsr;
default:
return SIGILL;
}
break;
- }
-#endif
default:
return SIGILL;
@@ -1961,7 +1816,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
*/
ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
- /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */
+ /*printk ("SIGFPE: FPU csr = %08x\n",ctx->fcr31); */
return SIGFPE;
}
@@ -1969,18 +1824,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
* Now we can safely write the result back to the register file.
*/
switch (rfmt) {
- case -1:{
-#if __mips >= 4
- cond = fpucondbit[MIPSInst_FD(ir) >> 2];
-#else
- cond = FPU_CSR_COND;
-#endif
+ case -1:
+
+ if (cpu_has_mips_4_5_r)
+ cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
+ else
+ cbit = FPU_CSR_COND;
if (rv.w)
- ctx->fcr31 |= cond;
+ ctx->fcr31 |= cbit;
else
- ctx->fcr31 &= ~cond;
+ ctx->fcr31 &= ~cbit;
break;
- }
+
case d_fmt:
DPTOREG(rv.d, MIPSInst_FD(ir));
break;
@@ -1990,11 +1845,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
case w_fmt:
SITOREG(rv.w, MIPSInst_FD(ir));
break;
-#if defined(__mips64)
case l_fmt:
+ if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+ return SIGILL;
+
DITOREG(rv.l, MIPSInst_FD(ir));
break;
-#endif
default:
return SIGILL;
}
@@ -2082,11 +1938,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
* ieee754_csr. But ieee754_csr.rm is ieee
* library modes. (not mips rounding mode)
*/
- /* convert to ieee library modes */
- ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr);
- /* revert to mips rounding mode */
- ieee754_csr.rm = mips_rm[ieee754_csr.rm];
}
if (has_fpu)
@@ -2099,58 +1951,8 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
/* SIGILL indicates a non-fpu instruction */
if (sig == SIGILL && xcp->cp0_epc != oldepc)
- /* but if epc has advanced, then ignore it */
+ /* but if EPC has advanced, then ignore it */
sig = 0;
return sig;
}
-
-#ifdef CONFIG_DEBUG_FS
-
-static int fpuemu_stat_get(void *data, u64 *val)
-{
- int cpu;
- unsigned long sum = 0;
- for_each_online_cpu(cpu) {
- struct mips_fpu_emulator_stats *ps;
- local_t *pv;
- ps = &per_cpu(fpuemustats, cpu);
- pv = (void *)ps + (unsigned long)data;
- sum += local_read(pv);
- }
- *val = sum;
- return 0;
-}
-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;
-
- if (!mips_debugfs_dir)
- return -ENODEV;
- dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
- if (!dir)
- return -ENOMEM;
-
-#define FPU_STAT_CREATE(M) \
- do { \
- d = debugfs_create_file(#M , S_IRUGO, dir, \
- (void *)offsetof(struct mips_fpu_emulator_stats, M), \
- &fops_fpuemu_stat); \
- if (!d) \
- return -ENOMEM; \
- } while (0)
-
- FPU_STAT_CREATE(emulated);
- FPU_STAT_CREATE(loads);
- FPU_STAT_CREATE(stores);
- FPU_STAT_CREATE(cp1ops);
- FPU_STAT_CREATE(cp1xops);
- FPU_STAT_CREATE(errors);
-
- return 0;
-}
-__initcall(debugfs_fpuemu);
-#endif
diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c
index c57c8adc42c..7f64577df98 100644
--- a/arch/mips/math-emu/dp_add.c
+++ b/arch/mips/math-emu/dp_add.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,24 +16,22 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y)
{
+ int s;
+
COMPXDP;
COMPYDP;
EXPLODEXDP;
EXPLODEYDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
FLUSHYDP;
@@ -52,8 +48,8 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -69,14 +65,14 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
return x;
- /* Infinity handling
- */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
if (xs == ys)
return x;
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
@@ -88,15 +84,14 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
return x;
- /* Zero handling
- */
-
+ /*
+ * Zero handling
+ */
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
else
- return ieee754dp_zero(ieee754_csr.rm ==
- IEEE754_RD);
+ return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
@@ -125,20 +120,24 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
assert(xm & DP_HIDDEN_BIT);
assert(ym & DP_HIDDEN_BIT);
- /* provide guard,round and stick bit space */
+ /*
+ * Provide guard,round and stick bit space.
+ */
xm <<= 3;
ym <<= 3;
if (xe > ye) {
- /* have to shift y fraction right to align
+ /*
+ * Have to shift y fraction right to align.
*/
- int s = xe - ye;
+ s = xe - ye;
ym = XDPSRS(ym, s);
ye += s;
} else if (ye > xe) {
- /* have to shift x fraction right to align
+ /*
+ * Have to shift x fraction right to align.
*/
- int s = ye - xe;
+ s = ye - xe;
xm = XDPSRS(xm, s);
xe += s;
}
@@ -146,14 +145,15 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
assert(xe <= DP_EMAX);
if (xs == ys) {
- /* generate 28 bit result of adding two 27 bit numbers
- * leaving result in xm,xs,xe
+ /*
+ * Generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm, xs and xe.
*/
xm = xm + ym;
xe = xe;
xs = xs;
- if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+ if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */
xm = XDPSRS1(xm);
xe++;
}
@@ -168,15 +168,16 @@ ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
xs = ys;
}
if (xm == 0)
- return ieee754dp_zero(ieee754_csr.rm ==
- IEEE754_RD);
+ return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
- /* normalize to rounding precision */
- while ((xm >> (DP_MBITS + 3)) == 0) {
+ /*
+ * Normalize to rounding precision.
+ */
+ while ((xm >> (DP_FBITS + 3)) == 0) {
xm <<= 1;
xe--;
}
-
}
- DPNORMRET2(xs, xe, xm, "add", x, y);
+
+ return ieee754dp_format(xs, xe, xm);
}
diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c
index 0f32486b0ed..30f95f6e9ac 100644
--- a/arch/mips/math-emu/dp_cmp.c
+++ b/arch/mips/math-emu/dp_cmp.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,16 +16,16 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig)
+int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig)
{
+ s64 vx;
+ s64 vy;
+
COMPXDP;
COMPYDP;
@@ -35,21 +33,21 @@ int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig)
EXPLODEYDP;
FLUSHXDP;
FLUSHYDP;
- CLEARCX; /* Even clear inexact flag here */
+ ieee754_clearcx(); /* Even clear inexact flag here */
if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
- SETCX(IEEE754_INVALID_OPERATION);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
if (cmp & IEEE754_CUN)
return 1;
if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
- if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
- return ieee754si_xcpt(0, "fcmpf", x);
+ if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
+ return 0;
}
return 0;
} else {
- s64 vx = x.bits;
- s64 vy = y.bits;
+ vx = x.bits;
+ vy = y.bits;
if (vx < 0)
vx = -vx ^ DP_SIGN_BIT;
diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c
index a1bce1b7c09..bef0e55e593 100644
--- a/arch/mips/math-emu/dp_div.c
+++ b/arch/mips/math-emu/dp_div.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,23 +16,24 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y)
{
+ u64 rm;
+ int re;
+ u64 bm;
+
COMPXDP;
COMPYDP;
EXPLODEXDP;
EXPLODEYDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
FLUSHYDP;
@@ -51,8 +50,8 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -68,12 +67,12 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
return x;
- /* Infinity handling
- */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
@@ -85,17 +84,17 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
return ieee754dp_inf(xs ^ ys);
- /* Zero handling
- */
-
+ /*
+ * Zero handling
+ */
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- SETCX(IEEE754_ZERO_DIVIDE);
- return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
+ ieee754_setcx(IEEE754_ZERO_DIVIDE);
+ return ieee754dp_inf(xs ^ ys);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
@@ -122,35 +121,34 @@ ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
xm <<= 3;
ym <<= 3;
- {
- /* now the dirty work */
-
- u64 rm = 0;
- int re = xe - ye;
- u64 bm;
-
- for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
- if (xm >= ym) {
- xm -= ym;
- rm |= bm;
- if (xm == 0)
- break;
- }
- xm <<= 1;
- }
- rm <<= 1;
- if (xm)
- rm |= 1; /* have remainder, set sticky */
+ /* now the dirty work */
- assert(rm);
+ rm = 0;
+ re = xe - ye;
- /* normalise rm to rounding precision ?
- */
- while ((rm >> (DP_MBITS + 3)) == 0) {
- rm <<= 1;
- re--;
+ for (bm = DP_MBIT(DP_FBITS + 2); bm; bm >>= 1) {
+ if (xm >= ym) {
+ xm -= ym;
+ rm |= bm;
+ if (xm == 0)
+ break;
}
+ xm <<= 1;
+ }
+
+ rm <<= 1;
+ if (xm)
+ rm |= 1; /* have remainder, set sticky */
- DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+ assert(rm);
+
+ /*
+ * Normalise rm to rounding precision ?
+ */
+ while ((rm >> (DP_FBITS + 3)) == 0) {
+ rm <<= 1;
+ re--;
}
+
+ return ieee754dp_format(xs == ys ? 0 : 1, re, rm);
}
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c
index 88571288c9e..10258f0afd6 100644
--- a/arch/mips/math-emu/dp_fint.c
+++ b/arch/mips/math-emu/dp_fint.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,21 +16,18 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-ieee754dp ieee754dp_fint(int x)
+union ieee754dp ieee754dp_fint(int x)
{
u64 xm;
int xe;
int xs;
- CLEARCX;
+ ieee754_clearcx();
if (x == 0)
return ieee754dp_zero(0);
@@ -51,29 +46,11 @@ ieee754dp ieee754dp_fint(int x)
xm = x;
}
-#if 1
/* normalize - result can never be inexact or overflow */
- xe = DP_MBITS;
- while ((xm >> DP_MBITS) == 0) {
+ xe = DP_FBITS;
+ while ((xm >> DP_FBITS) == 0) {
xm <<= 1;
xe--;
}
return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
-#else
- /* normalize */
- xe = DP_MBITS + 3;
- while ((xm >> (DP_MBITS + 3)) == 0) {
- xm <<= 1;
- xe--;
- }
- DPNORMRET1(xs, xe, xm, "fint", x);
-#endif
-}
-
-ieee754dp ieee754dp_funs(unsigned int u)
-{
- if ((int) u < 0)
- return ieee754dp_add(ieee754dp_1e31(),
- ieee754dp_fint(u & ~(1 << 31)));
- return ieee754dp_fint(u);
}
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c
index 14fc01ec742..a267c2e39d7 100644
--- a/arch/mips/math-emu/dp_flong.c
+++ b/arch/mips/math-emu/dp_flong.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,21 +16,18 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-ieee754dp ieee754dp_flong(s64 x)
+union ieee754dp ieee754dp_flong(s64 x)
{
u64 xm;
int xe;
int xs;
- CLEARCX;
+ ieee754_clearcx();
if (x == 0)
return ieee754dp_zero(0);
@@ -52,26 +47,19 @@ ieee754dp ieee754dp_flong(s64 x)
}
/* normalize */
- xe = DP_MBITS + 3;
- if (xm >> (DP_MBITS + 1 + 3)) {
+ xe = DP_FBITS + 3;
+ if (xm >> (DP_FBITS + 1 + 3)) {
/* shunt out overflow bits */
- while (xm >> (DP_MBITS + 1 + 3)) {
+ while (xm >> (DP_FBITS + 1 + 3)) {
XDPSRSX1();
}
} else {
/* normalize in grs extended double precision */
- while ((xm >> (DP_MBITS + 3)) == 0) {
+ while ((xm >> (DP_FBITS + 3)) == 0) {
xm <<= 1;
xe--;
}
}
- DPNORMRET1(xs, xe, xm, "dp_flong", x);
-}
-ieee754dp ieee754dp_fulong(u64 u)
-{
- if ((s64) u < 0)
- return ieee754dp_add(ieee754dp_1e63(),
- ieee754dp_flong(u & ~(1ULL << 63)));
- return ieee754dp_flong(u);
+ return ieee754dp_format(xs, xe, xm);
}
diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c
deleted file mode 100644
index cb15a5eaecb..00000000000
--- a/arch/mips/math-emu/dp_frexp.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* IEEE754 floating point arithmetic
- * double precision: common utilities
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754dp.h"
-
-/* close to ieeep754dp_logb
-*/
-ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
-{
- COMPXDP;
- CLEARCX;
- EXPLODEXDP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- case IEEE754_CLASS_QNAN:
- case IEEE754_CLASS_INF:
- case IEEE754_CLASS_ZERO:
- *eptr = 0;
- return x;
- case IEEE754_CLASS_DNORM:
- DPDNORMX;
- break;
- case IEEE754_CLASS_NORM:
- break;
- }
- *eptr = xe + 1;
- return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
-}
diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c
index daed6834dc1..ffb69c5830b 100644
--- a/arch/mips/math-emu/dp_fsp.c
+++ b/arch/mips/math-emu/dp_fsp.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,56 +16,58 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
+#include "ieee754sp.h"
#include "ieee754dp.h"
-ieee754dp ieee754dp_fsp(ieee754sp x)
+union ieee754dp ieee754dp_fsp(union ieee754sp x)
{
COMPXSP;
EXPLODEXSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
switch (xc) {
case IEEE754_CLASS_SNAN:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
+
case IEEE754_CLASS_QNAN:
return ieee754dp_nanxcpt(builddp(xs,
DP_EMAX + 1 + DP_EBIAS,
((u64) xm
- << (DP_MBITS -
- SP_MBITS))), "fsp",
- x);
+ << (DP_FBITS -
+ SP_FBITS))));
case IEEE754_CLASS_INF:
return ieee754dp_inf(xs);
+
case IEEE754_CLASS_ZERO:
return ieee754dp_zero(xs);
+
case IEEE754_CLASS_DNORM:
/* normalize */
- while ((xm >> SP_MBITS) == 0) {
+ while ((xm >> SP_FBITS) == 0) {
xm <<= 1;
xe--;
}
break;
+
case IEEE754_CLASS_NORM:
break;
}
- /* CAN'T possibly overflow,underflow, or need rounding
+ /*
+ * Can't possibly overflow,underflow, or need rounding
*/
/* drop the hidden bit */
xm &= ~SP_HIDDEN_BIT;
return builddp(xs, xe + DP_EBIAS,
- (u64) xm << (DP_MBITS - SP_MBITS));
+ (u64) xm << (DP_FBITS - SP_FBITS));
}
diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c
deleted file mode 100644
index 151127e59f5..00000000000
--- a/arch/mips/math-emu/dp_logb.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* IEEE754 floating point arithmetic
- * double precision: common utilities
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754dp.h"
-
-ieee754dp ieee754dp_logb(ieee754dp x)
-{
- COMPXDP;
-
- CLEARCX;
-
- EXPLODEXDP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- return ieee754dp_nanxcpt(x, "logb", x);
- case IEEE754_CLASS_QNAN:
- return x;
- case IEEE754_CLASS_INF:
- return ieee754dp_inf(0);
- case IEEE754_CLASS_ZERO:
- return ieee754dp_inf(1);
- case IEEE754_CLASS_DNORM:
- DPDNORMX;
- break;
- case IEEE754_CLASS_NORM:
- break;
- }
- return ieee754dp_fint(xe);
-}
diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c
deleted file mode 100644
index b01f9cf6d40..00000000000
--- a/arch/mips/math-emu/dp_modf.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* IEEE754 floating point arithmetic
- * double precision: common utilities
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754dp.h"
-
-/* modf function is always exact for a finite number
-*/
-ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp *ip)
-{
- COMPXDP;
-
- CLEARCX;
-
- EXPLODEXDP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- case IEEE754_CLASS_QNAN:
- case IEEE754_CLASS_INF:
- case IEEE754_CLASS_ZERO:
- *ip = x;
- return x;
- case IEEE754_CLASS_DNORM:
- /* far to small */
- *ip = ieee754dp_zero(xs);
- return x;
- case IEEE754_CLASS_NORM:
- break;
- }
- if (xe < 0) {
- *ip = ieee754dp_zero(xs);
- return x;
- }
- if (xe >= DP_MBITS) {
- *ip = x;
- return ieee754dp_zero(xs);
- }
- /* generate ipart mantissa by clearing bottom bits
- */
- *ip = builddp(xs, xe + DP_EBIAS,
- ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
- ~DP_HIDDEN_BIT);
-
- /* generate fpart mantissa by clearing top bits
- * and normalizing (must be able to normalize)
- */
- xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
- if (xm == 0)
- return ieee754dp_zero(xs);
-
- while ((xm >> DP_MBITS) == 0) {
- xm <<= 1;
- xe--;
- }
- return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
-}
diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c
index 09175f46192..d3acdedb5b9 100644
--- a/arch/mips/math-emu/dp_mul.c
+++ b/arch/mips/math-emu/dp_mul.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,23 +16,32 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_mul(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;
+
COMPXDP;
COMPYDP;
EXPLODEXDP;
EXPLODEYDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
FLUSHYDP;
@@ -51,8 +58,8 @@ ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -68,12 +75,13 @@ ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
return x;
- /* Infinity handling */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
@@ -107,70 +115,59 @@ ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
/* rm = xm * ym, re = xe+ye basically */
assert(xm & DP_HIDDEN_BIT);
assert(ym & DP_HIDDEN_BIT);
- {
- int re = xe + ye;
- int rs = xs ^ ys;
- u64 rm;
- /* shunt to top of word */
- xm <<= 64 - (DP_MBITS + 1);
- ym <<= 64 - (DP_MBITS + 1);
+ re = xe + ye;
+ rs = xs ^ ys;
+
+ /* shunt to top of word */
+ xm <<= 64 - (DP_FBITS + 1);
+ ym <<= 64 - (DP_FBITS + 1);
- /* multiply 32bits xm,ym to give high 32bits rm with stickness
- */
+ /*
+ * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+ */
- /* 32 * 32 => 64 */
+ /* 32 * 32 => 64 */
#define DPXMULT(x, y) ((u64)(x) * (u64)y)
- {
- unsigned lxm = xm;
- unsigned hxm = xm >> 32;
- unsigned lym = ym;
- unsigned hym = ym >> 32;
- u64 lrm;
- u64 hrm;
-
- lrm = DPXMULT(lxm, lym);
- hrm = DPXMULT(hxm, hym);
-
- {
- u64 t = DPXMULT(lxm, hym);
- {
- u64 at =
- lrm + (t << 32);
- hrm += at < lrm;
- lrm = at;
- }
- hrm = hrm + (t >> 32);
- }
-
- {
- u64 t = DPXMULT(hxm, lym);
- {
- u64 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_MBITS + 1 + 3))) |
- ((rm << (DP_MBITS + 1 + 3)) != 0);
+ 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_MBITS + 1 + 3 + 1))) |
- ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
- }
- assert(rm & (DP_HIDDEN_BIT << 3));
- DPNORMRET2(rs, re, rm, "mul", x, y);
+ } else {
+ rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
+ ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
}
+ assert(rm & (DP_HIDDEN_BIT << 3));
+
+ return ieee754dp_format(rs, re, rm);
}
diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c
deleted file mode 100644
index 6f5df438dda..00000000000
--- a/arch/mips/math-emu/dp_scalb.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* IEEE754 floating point arithmetic
- * double precision: common utilities
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754dp.h"
-
-ieee754dp ieee754dp_scalb(ieee754dp x, int n)
-{
- COMPXDP;
-
- CLEARCX;
-
- EXPLODEXDP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- return ieee754dp_nanxcpt(x, "scalb", x, n);
- case IEEE754_CLASS_QNAN:
- case IEEE754_CLASS_INF:
- case IEEE754_CLASS_ZERO:
- return x;
- case IEEE754_CLASS_DNORM:
- DPDNORMX;
- break;
- case IEEE754_CLASS_NORM:
- break;
- }
- DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
-}
-
-
-ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
-{
- return ieee754dp_scalb(x, n);
-}
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
index 79ce2673a71..bccbe90efce 100644
--- a/arch/mips/math-emu/dp_simple.c
+++ b/arch/mips/math-emu/dp_simple.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,33 +16,17 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-int ieee754dp_finite(ieee754dp x)
-{
- return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
-}
-
-ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
-{
- CLEARCX;
- DPSIGN(x) = DPSIGN(y);
- return x;
-}
-
-
-ieee754dp ieee754dp_neg(ieee754dp x)
+union ieee754dp ieee754dp_neg(union ieee754dp x)
{
COMPXDP;
EXPLODEXDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
/*
@@ -55,30 +37,29 @@ ieee754dp ieee754dp_neg(ieee754dp x)
DPSIGN(x) ^= 1;
if (xc == IEEE754_CLASS_SNAN) {
- ieee754dp y = ieee754dp_indef();
- SETCX(IEEE754_INVALID_OPERATION);
+ union ieee754dp y = ieee754dp_indef();
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
DPSIGN(y) = DPSIGN(x);
- return ieee754dp_nanxcpt(y, "neg");
+ return ieee754dp_nanxcpt(y);
}
return x;
}
-
-ieee754dp ieee754dp_abs(ieee754dp x)
+union ieee754dp ieee754dp_abs(union ieee754dp x)
{
COMPXDP;
EXPLODEXDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
/* Clear sign ALWAYS, irrespective of NaN */
DPSIGN(x) = 0;
if (xc == IEEE754_CLASS_SNAN) {
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "abs");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
}
return x;
diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c
index b874d60a942..041bbb6124b 100644
--- a/arch/mips/math-emu/dp_sqrt.c
+++ b/arch/mips/math-emu/dp_sqrt.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,12 +16,9 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
static const unsigned table[] = {
@@ -34,44 +29,49 @@ static const unsigned table[] = {
1742, 661, 130
};
-ieee754dp ieee754dp_sqrt(ieee754dp x)
+union ieee754dp ieee754dp_sqrt(union ieee754dp x)
{
struct _ieee754_csr oldcsr;
- ieee754dp y, z, t;
+ union ieee754dp y, z, t;
unsigned scalx, yh;
COMPXDP;
EXPLODEXDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
/* x == INF or NAN? */
switch (xc) {
case IEEE754_CLASS_QNAN:
/* sqrt(Nan) = Nan */
- return ieee754dp_nanxcpt(x, "sqrt");
+ return ieee754dp_nanxcpt(x);
+
case IEEE754_CLASS_SNAN:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
+
case IEEE754_CLASS_ZERO:
/* sqrt(0) = 0 */
return x;
+
case IEEE754_CLASS_INF:
if (xs) {
/* sqrt(-Inf) = Nan */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
}
/* sqrt(+Inf) = Inf */
return x;
+
case IEEE754_CLASS_DNORM:
DPDNORMX;
/* fall through */
+
case IEEE754_CLASS_NORM:
if (xs) {
/* sqrt(-x) = Nan */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
}
break;
}
@@ -80,7 +80,7 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)
oldcsr = ieee754_csr;
ieee754_csr.mx &= ~IEEE754_INEXACT;
ieee754_csr.sx &= ~IEEE754_INEXACT;
- ieee754_csr.rm = IEEE754_RN;
+ ieee754_csr.rm = FPU_CSR_RN;
/* adjust exponent to prevent overflow */
scalx = 0;
@@ -110,19 +110,19 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)
/* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
/* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
z = t = ieee754dp_mul(y, y);
- t.parts.bexp += 0x001;
+ t.bexp += 0x001;
t = ieee754dp_add(t, z);
z = ieee754dp_mul(ieee754dp_sub(x, z), y);
/* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */
t = ieee754dp_div(z, ieee754dp_add(t, x));
- t.parts.bexp += 0x001;
+ t.bexp += 0x001;
y = ieee754dp_add(y, t);
/* twiddle last bit to force y correctly rounded */
/* set RZ, clear INEX flag */
- ieee754_csr.rm = IEEE754_RZ;
+ ieee754_csr.rm = FPU_CSR_RZ;
ieee754_csr.sx &= ~IEEE754_INEXACT;
/* t=x/y; ...chopped quotient, possibly inexact */
@@ -139,10 +139,10 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)
oldcsr.sx |= IEEE754_INEXACT;
switch (oldcsr.rm) {
- case IEEE754_RP:
+ case FPU_CSR_RU:
y.bits += 1;
/* drop through */
- case IEEE754_RN:
+ case FPU_CSR_RN:
t.bits += 1;
break;
}
@@ -155,7 +155,7 @@ ieee754dp ieee754dp_sqrt(ieee754dp x)
}
/* py[n0]=py[n0]+scalx; ...scale back y */
- y.parts.bexp += scalx;
+ y.bexp += scalx;
/* restore rounding mode, possibly set inexact */
ieee754_csr = oldcsr;
diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c
index 91e0a4b5cbc..7a174029043 100644
--- a/arch/mips/math-emu/dp_sub.c
+++ b/arch/mips/math-emu/dp_sub.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,23 +16,22 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)
{
+ int s;
+
COMPXDP;
COMPYDP;
EXPLODEXDP;
EXPLODEYDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
FLUSHYDP;
@@ -51,8 +48,8 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -68,14 +65,14 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
return x;
- /* Infinity handling
- */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
if (xs != ys)
return x;
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_indef();
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
@@ -87,15 +84,14 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
return x;
- /* Zero handling
- */
-
+ /*
+ * Zero handling
+ */
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs != ys)
return x;
else
- return ieee754dp_zero(ieee754_csr.rm ==
- IEEE754_RD);
+ return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
@@ -136,15 +132,17 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
ym <<= 3;
if (xe > ye) {
- /* have to shift y fraction right to align
+ /*
+ * Have to shift y fraction right to align
*/
- int s = xe - ye;
+ s = xe - ye;
ym = XDPSRS(ym, s);
ye += s;
} else if (ye > xe) {
- /* have to shift x fraction right to align
+ /*
+ * Have to shift x fraction right to align
*/
- int s = ye - xe;
+ s = ye - xe;
xm = XDPSRS(xm, s);
xe += s;
}
@@ -158,7 +156,7 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
xe = xe;
xs = xs;
- if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+ if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */
xm = XDPSRS1(xm); /* shift preserving sticky */
xe++;
}
@@ -173,7 +171,7 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
xs = ys;
}
if (xm == 0) {
- if (ieee754_csr.rm == IEEE754_RD)
+ if (ieee754_csr.rm == FPU_CSR_RD)
return ieee754dp_zero(1); /* round negative inf. => sign = -1 */
else
return ieee754dp_zero(0); /* other round modes => sign = 1 */
@@ -181,10 +179,11 @@ ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
/* normalize to rounding precision
*/
- while ((xm >> (DP_MBITS + 3)) == 0) {
+ while ((xm >> (DP_FBITS + 3)) == 0) {
xm <<= 1;
xe--;
}
}
- DPNORMRET2(xs, xe, xm, "sub", x, y);
+
+ return ieee754dp_format(xs, xe, xm);
}
diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c
index 0ebe8598b94..6ffc336c530 100644
--- a/arch/mips/math-emu/dp_tint.c
+++ b/arch/mips/math-emu/dp_tint.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,20 +16,21 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
-#include <linux/kernel.h>
#include "ieee754dp.h"
-int ieee754dp_tint(ieee754dp x)
+int ieee754dp_tint(union ieee754dp x)
{
+ u64 residue;
+ int round;
+ int sticky;
+ int odd;
+
COMPXDP;
- CLEARCX;
+ ieee754_clearcx();
EXPLODEXDP;
FLUSHXDP;
@@ -40,10 +39,12 @@ int ieee754dp_tint(ieee754dp x)
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754si_indef();
+
case IEEE754_CLASS_ZERO:
return 0;
+
case IEEE754_CLASS_DNORM:
case IEEE754_CLASS_NORM:
break;
@@ -51,44 +52,39 @@ int ieee754dp_tint(ieee754dp x)
if (xe > 31) {
/* Set invalid. We will only use overflow for floating
point overflow */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754si_indef();
}
/* oh gawd */
- if (xe > DP_MBITS) {
- xm <<= xe - DP_MBITS;
- } else if (xe < DP_MBITS) {
- u64 residue;
- int round;
- int sticky;
- int odd;
-
+ if (xe > DP_FBITS) {
+ xm <<= xe - DP_FBITS;
+ } else if (xe < DP_FBITS) {
if (xe < -1) {
residue = xm;
round = 0;
sticky = residue != 0;
xm = 0;
} else {
- residue = xm << (64 - DP_MBITS + xe);
+ residue = xm << (64 - DP_FBITS + xe);
round = (residue >> 63) != 0;
sticky = (residue << 1) != 0;
- xm >>= DP_MBITS - xe;
+ xm >>= DP_FBITS - xe;
}
/* Note: At this point upper 32 bits of xm are guaranteed
to be zero */
odd = (xm & 0x1) != 0x0;
switch (ieee754_csr.rm) {
- case IEEE754_RN:
+ case FPU_CSR_RN:
if (round && (sticky || odd))
xm++;
break;
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
break;
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if ((round || sticky) && !xs)
xm++;
break;
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if ((round || sticky) && xs)
xm++;
break;
@@ -96,27 +92,14 @@ int ieee754dp_tint(ieee754dp x)
/* look for valid corner case 0x80000000 */
if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
/* This can happen after rounding */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754si_indef();
}
if (round || sticky)
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_INEXACT);
}
if (xs)
return -xm;
else
return xm;
}
-
-
-unsigned int ieee754dp_tuns(ieee754dp x)
-{
- ieee754dp hb = ieee754dp_1e31();
-
- /* what if x < 0 ?? */
- if (ieee754dp_lt(x, hb))
- return (unsigned) ieee754dp_tint(x);
-
- return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) |
- ((unsigned) 1 << 31);
-}
diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c
index 133ce2ba001..9cdc145b75e 100644
--- a/arch/mips/math-emu/dp_tlong.c
+++ b/arch/mips/math-emu/dp_tlong.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,19 +16,21 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754dp.h"
-s64 ieee754dp_tlong(ieee754dp x)
+s64 ieee754dp_tlong(union ieee754dp x)
{
+ u64 residue;
+ int round;
+ int sticky;
+ int odd;
+
COMPXDP;
- CLEARCX;
+ ieee754_clearcx();
EXPLODEXDP;
FLUSHXDP;
@@ -39,10 +39,12 @@ s64 ieee754dp_tlong(ieee754dp x)
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754di_indef();
+
case IEEE754_CLASS_ZERO:
return 0;
+
case IEEE754_CLASS_DNORM:
case IEEE754_CLASS_NORM:
break;
@@ -53,18 +55,13 @@ s64 ieee754dp_tlong(ieee754dp x)
return -0x8000000000000000LL;
/* Set invalid. We will only use overflow for floating
point overflow */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754di_indef();
}
/* oh gawd */
- if (xe > DP_MBITS) {
- xm <<= xe - DP_MBITS;
- } else if (xe < DP_MBITS) {
- u64 residue;
- int round;
- int sticky;
- int odd;
-
+ if (xe > DP_FBITS) {
+ xm <<= xe - DP_FBITS;
+ } else if (xe < DP_FBITS) {
if (xe < -1) {
residue = xm;
round = 0;
@@ -75,51 +72,38 @@ s64 ieee754dp_tlong(ieee754dp x)
* so we do it in two steps. Be aware that xe
* may be -1 */
residue = xm << (xe + 1);
- residue <<= 63 - DP_MBITS;
+ residue <<= 63 - DP_FBITS;
round = (residue >> 63) != 0;
sticky = (residue << 1) != 0;
- xm >>= DP_MBITS - xe;
+ xm >>= DP_FBITS - xe;
}
odd = (xm & 0x1) != 0x0;
switch (ieee754_csr.rm) {
- case IEEE754_RN:
+ case FPU_CSR_RN:
if (round && (sticky || odd))
xm++;
break;
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
break;
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if ((round || sticky) && !xs)
xm++;
break;
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if ((round || sticky) && xs)
xm++;
break;
}
if ((xm >> 63) != 0) {
/* This can happen after rounding */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754di_indef();
}
if (round || sticky)
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_INEXACT);
}
if (xs)
return -xm;
else
return xm;
}
-
-
-u64 ieee754dp_tulong(ieee754dp x)
-{
- ieee754dp hb = ieee754dp_1e63();
-
- /* what if x < 0 ?? */
- if (ieee754dp_lt(x, hb))
- return (u64) ieee754dp_tlong(x);
-
- return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
- (1ULL << 63);
-}
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index 7ea622ab8da..4f514f3724c 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -1,30 +1,12 @@
-#include <linux/compiler.h>
-#include <linux/mm.h>
-#include <linux/signal.h>
-#include <linux/smp.h>
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/byteorder.h>
-#include <asm/cpu.h>
-#include <asm/inst.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
#include <asm/branch.h>
-#include <asm/mipsregs.h>
#include <asm/cacheflush.h>
-
#include <asm/fpu_emulator.h>
+#include <asm/inst.h>
+#include <asm/mipsregs.h>
+#include <asm/uaccess.h>
#include "ieee754.h"
-/* Strap kernel emulator for full MIPS IV emulation */
-
-#ifdef __mips
-#undef __mips
-#endif
-#define __mips 4
-
/*
* Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when
* we have to emulate the instruction in a COP1 branch delay slot. Do
@@ -59,13 +41,11 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
(ir == 0)) {
/* NOP is easy */
regs->cp0_epc = cpc;
- regs->cp0_cause &= ~CAUSEF_BD;
+ clear_delay_slot(regs);
return 0;
}
-#ifdef DSEMUL_TRACE
- printk("dsemul %lx %lx\n", regs->cp0_epc, cpc);
-#endif
+ pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
/*
* The strategy is to push the instruction onto the user stack
@@ -167,9 +147,8 @@ int do_dsemulret(struct pt_regs *xcp)
* emulating the branch delay instruction.
*/
-#ifdef DSEMUL_TRACE
- printk("dsemulret\n");
-#endif
+ pr_debug("dsemulret\n");
+
if (__get_user(epc, &fr->epc)) { /* Saved EPC */
/* This is not a good situation to be in */
force_sig(SIGBUS, current);
diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c
index 0015cf1989d..8e97acbbe22 100644
--- a/arch/mips/math-emu/ieee754.c
+++ b/arch/mips/math-emu/ieee754.c
@@ -10,8 +10,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -23,105 +21,74 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <linux/compiler.h>
-#include "ieee754int.h"
+#include "ieee754.h"
#include "ieee754sp.h"
#include "ieee754dp.h"
-#define DP_EBIAS 1023
-#define DP_EMIN (-1022)
-#define DP_EMAX 1023
-
-#define SP_EBIAS 127
-#define SP_EMIN (-126)
-#define SP_EMAX 127
-
-/* special constants
-*/
-
-
-#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
-#define SPSTR(s, b, m) {m, b, s}
-#define DPSTR(s, b, mh, ml) {ml, mh, b, s}
-#endif
+/*
+ * Special constants
+ */
-#ifdef __MIPSEB__
-#define SPSTR(s, b, m) {s, b, m}
-#define DPSTR(s, b, mh, ml) {s, b, mh, ml}
-#endif
+/*
+ * Older GCC requires the inner braces for initialization of union ieee754dp's
+ * anonymous struct member. Without an error will result.
+ */
+#define xPCNST(s, b, m, ebias) \
+{ \
+ { \
+ .sign = (s), \
+ .bexp = (b) + ebias, \
+ .mant = (m) \
+ } \
+}
-const struct ieee754dp_konst __ieee754dp_spcvals[] = {
- DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */
- DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */
- DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */
- DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */
- DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */
- DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */
- DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */
- DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */
- DPSTR(0, DP_EMAX+1+DP_EBIAS, 0x7FFFF, 0xFFFFFFFF), /* + indef quiet Nan */
- DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */
- DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */
- DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */
- DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */
- DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */
- DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */
- DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */
- DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */
-};
+#define DPCNST(s, b, m) \
+ xPCNST(s, b, m, DP_EBIAS)
-const struct ieee754sp_konst __ieee754sp_spcvals[] = {
- SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */
- SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */
- SPSTR(0, SP_EBIAS, 0), /* + 1.0 */
- SPSTR(1, SP_EBIAS, 0), /* - 1.0 */
- SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */
- SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */
- SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */
- SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */
- SPSTR(0, SP_EMAX+1+SP_EBIAS, 0x3FFFFF), /* + indef quiet Nan */
- SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */
- SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */
- SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */
- SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */
- SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */
- SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */
- SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */
- SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */
+const union ieee754dp __ieee754dp_spcvals[] = {
+ DPCNST(0, DP_EMIN - 1, 0x0000000000000ULL), /* + zero */
+ DPCNST(1, DP_EMIN - 1, 0x0000000000000ULL), /* - zero */
+ DPCNST(0, 0, 0x0000000000000ULL), /* + 1.0 */
+ DPCNST(1, 0, 0x0000000000000ULL), /* - 1.0 */
+ DPCNST(0, 3, 0x4000000000000ULL), /* + 10.0 */
+ DPCNST(1, 3, 0x4000000000000ULL), /* - 10.0 */
+ DPCNST(0, DP_EMAX + 1, 0x0000000000000ULL), /* + infinity */
+ DPCNST(1, DP_EMAX + 1, 0x0000000000000ULL), /* - infinity */
+ DPCNST(0, DP_EMAX + 1, 0x7FFFFFFFFFFFFULL), /* + indef quiet Nan */
+ DPCNST(0, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* + max */
+ DPCNST(1, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* - max */
+ DPCNST(0, DP_EMIN, 0x0000000000000ULL), /* + min normal */
+ DPCNST(1, DP_EMIN, 0x0000000000000ULL), /* - min normal */
+ DPCNST(0, DP_EMIN - 1, 0x0000000000001ULL), /* + min denormal */
+ DPCNST(1, DP_EMIN - 1, 0x0000000000001ULL), /* - min denormal */
+ DPCNST(0, 31, 0x0000000000000ULL), /* + 1.0e31 */
+ DPCNST(0, 63, 0x0000000000000ULL), /* + 1.0e63 */
};
+#define SPCNST(s, b, m) \
+ xPCNST(s, b, m, SP_EBIAS)
-int ieee754si_xcpt(int r, const char *op, ...)
-{
- struct ieee754xctx ax;
-
- if (!TSTX())
- return r;
- ax.op = op;
- ax.rt = IEEE754_RT_SI;
- ax.rv.si = r;
- va_start(ax.ap, op);
- ieee754_xcpt(&ax);
- va_end(ax.ap);
- return ax.rv.si;
-}
-
-s64 ieee754di_xcpt(s64 r, const char *op, ...)
-{
- struct ieee754xctx ax;
-
- if (!TSTX())
- return r;
- ax.op = op;
- ax.rt = IEEE754_RT_DI;
- ax.rv.di = r;
- va_start(ax.ap, op);
- ieee754_xcpt(&ax);
- va_end(ax.ap);
- return ax.rv.di;
-}
+const union ieee754sp __ieee754sp_spcvals[] = {
+ SPCNST(0, SP_EMIN - 1, 0x000000), /* + zero */
+ SPCNST(1, SP_EMIN - 1, 0x000000), /* - zero */
+ SPCNST(0, 0, 0x000000), /* + 1.0 */
+ SPCNST(1, 0, 0x000000), /* - 1.0 */
+ SPCNST(0, 3, 0x200000), /* + 10.0 */
+ SPCNST(1, 3, 0x200000), /* - 10.0 */
+ SPCNST(0, SP_EMAX + 1, 0x000000), /* + infinity */
+ SPCNST(1, SP_EMAX + 1, 0x000000), /* - infinity */
+ SPCNST(0, SP_EMAX + 1, 0x3FFFFF), /* + indef quiet Nan */
+ SPCNST(0, SP_EMAX, 0x7FFFFF), /* + max normal */
+ SPCNST(1, SP_EMAX, 0x7FFFFF), /* - max normal */
+ SPCNST(0, SP_EMIN, 0x000000), /* + min normal */
+ SPCNST(1, SP_EMIN, 0x000000), /* - min normal */
+ SPCNST(0, SP_EMIN - 1, 0x000001), /* + min denormal */
+ SPCNST(1, SP_EMIN - 1, 0x000001), /* - min denormal */
+ SPCNST(0, 31, 0x000000), /* + 1.0e31 */
+ SPCNST(0, 63, 0x000000), /* + 1.0e63 */
+};
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
index 22796e01206..43c4fb522ac 100644
--- a/arch/mips/math-emu/ieee754.h
+++ b/arch/mips/math-emu/ieee754.h
@@ -13,7 +13,7 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Nov 7, 2000
* Modification to allow integration with Linux kernel
@@ -24,186 +24,93 @@
#ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H
#define __ARCH_MIPS_MATH_EMU_IEEE754_H
+#include <linux/compiler.h>
#include <asm/byteorder.h>
+#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
+#include <asm/bitfield.h>
-/*
- * Not very pretty, but the Linux kernel's normal va_list definition
- * does not allow it to be used as a structure element, as it is here.
- */
-#ifndef _STDARG_H
-#include <stdarg.h>
-#endif
-
-#ifdef __LITTLE_ENDIAN
-struct ieee754dp_konst {
- unsigned mantlo:32;
- unsigned manthi:20;
- unsigned bexp:11;
- unsigned sign:1;
-};
-struct ieee754sp_konst {
- unsigned mant:23;
- unsigned bexp:8;
- unsigned sign:1;
-};
-
-typedef union _ieee754dp {
- struct ieee754dp_konst oparts;
+union ieee754dp {
struct {
- u64 mant:52;
- unsigned int bexp:11;
- unsigned int sign:1;
- } parts;
+ __BITFIELD_FIELD(unsigned int sign:1,
+ __BITFIELD_FIELD(unsigned int bexp:11,
+ __BITFIELD_FIELD(u64 mant:52,
+ ;)))
+ };
u64 bits;
- double d;
-} ieee754dp;
-
-typedef union _ieee754sp {
- struct ieee754sp_konst parts;
- float f;
- u32 bits;
-} ieee754sp;
-#endif
-
-#ifdef __BIG_ENDIAN
-struct ieee754dp_konst {
- unsigned sign:1;
- unsigned bexp:11;
- unsigned manthi:20;
- unsigned mantlo:32;
};
-typedef union _ieee754dp {
- struct ieee754dp_konst oparts;
+union ieee754sp {
struct {
- unsigned int sign:1;
- unsigned int bexp:11;
- u64 mant:52;
- } parts;
- double d;
- u64 bits;
-} ieee754dp;
-
-struct ieee754sp_konst {
- unsigned sign:1;
- unsigned bexp:8;
- unsigned mant:23;
-};
-
-typedef union _ieee754sp {
- struct ieee754sp_konst parts;
- float f;
+ __BITFIELD_FIELD(unsigned sign:1,
+ __BITFIELD_FIELD(unsigned bexp:8,
+ __BITFIELD_FIELD(unsigned mant:23,
+ ;)))
+ };
u32 bits;
-} ieee754sp;
-#endif
+};
/*
* single precision (often aka float)
*/
-int ieee754sp_finite(ieee754sp x);
-int ieee754sp_class(ieee754sp x);
-
-ieee754sp ieee754sp_abs(ieee754sp x);
-ieee754sp ieee754sp_neg(ieee754sp x);
-ieee754sp ieee754sp_scalb(ieee754sp x, int);
-ieee754sp ieee754sp_logb(ieee754sp x);
-
-/* x with sign of y */
-ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
-
-ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
-ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
-ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
-ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
-
-ieee754sp ieee754sp_fint(int x);
-ieee754sp ieee754sp_funs(unsigned x);
-ieee754sp ieee754sp_flong(s64 x);
-ieee754sp ieee754sp_fulong(u64 x);
-ieee754sp ieee754sp_fdp(ieee754dp x);
-
-int ieee754sp_tint(ieee754sp x);
-unsigned int ieee754sp_tuns(ieee754sp x);
-s64 ieee754sp_tlong(ieee754sp x);
-u64 ieee754sp_tulong(ieee754sp x);
-
-int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig);
-/*
- * basic sp math
- */
-ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
-ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
-ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+int ieee754sp_class(union ieee754sp x);
-ieee754sp ieee754sp_ceil(ieee754sp x);
-ieee754sp ieee754sp_floor(ieee754sp x);
-ieee754sp ieee754sp_trunc(ieee754sp x);
+union ieee754sp ieee754sp_abs(union ieee754sp x);
+union ieee754sp ieee754sp_neg(union ieee754sp x);
-ieee754sp ieee754sp_sqrt(ieee754sp x);
+union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y);
-/*
- * double precision (often aka double)
-*/
-int ieee754dp_finite(ieee754dp x);
-int ieee754dp_class(ieee754dp x);
+union ieee754sp ieee754sp_fint(int x);
+union ieee754sp ieee754sp_flong(s64 x);
+union ieee754sp ieee754sp_fdp(union ieee754dp x);
-/* x with sign of y */
-ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+int ieee754sp_tint(union ieee754sp x);
+s64 ieee754sp_tlong(union ieee754sp x);
-ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
-ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
-ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
-ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cop, int sig);
-ieee754dp ieee754dp_abs(ieee754dp x);
-ieee754dp ieee754dp_neg(ieee754dp x);
-ieee754dp ieee754dp_scalb(ieee754dp x, int);
+union ieee754sp ieee754sp_sqrt(union ieee754sp x);
-/* return exponent as integer in floating point format
- */
-ieee754dp ieee754dp_logb(ieee754dp x);
+/*
+ * double precision (often aka double)
+*/
+int ieee754dp_class(union ieee754dp x);
-ieee754dp ieee754dp_fint(int x);
-ieee754dp ieee754dp_funs(unsigned x);
-ieee754dp ieee754dp_flong(s64 x);
-ieee754dp ieee754dp_fulong(u64 x);
-ieee754dp ieee754dp_fsp(ieee754sp x);
+union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y);
-ieee754dp ieee754dp_ceil(ieee754dp x);
-ieee754dp ieee754dp_floor(ieee754dp x);
-ieee754dp ieee754dp_trunc(ieee754dp x);
+union ieee754dp ieee754dp_abs(union ieee754dp x);
+union ieee754dp ieee754dp_neg(union ieee754dp x);
-int ieee754dp_tint(ieee754dp x);
-unsigned int ieee754dp_tuns(ieee754dp x);
-s64 ieee754dp_tlong(ieee754dp x);
-u64 ieee754dp_tulong(ieee754dp x);
+union ieee754dp ieee754dp_fint(int x);
+union ieee754dp ieee754dp_flong(s64 x);
+union ieee754dp ieee754dp_fsp(union ieee754sp x);
-int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig);
-/*
- * basic sp math
- */
-ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
-ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
-ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+int ieee754dp_tint(union ieee754dp x);
+s64 ieee754dp_tlong(union ieee754dp x);
-ieee754dp ieee754dp_ceil(ieee754dp x);
-ieee754dp ieee754dp_floor(ieee754dp x);
-ieee754dp ieee754dp_trunc(ieee754dp x);
+int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cop, int sig);
-ieee754dp ieee754dp_sqrt(ieee754dp x);
+union ieee754dp ieee754dp_sqrt(union ieee754dp x);
/* 5 types of floating point number
*/
-#define IEEE754_CLASS_NORM 0x00
-#define IEEE754_CLASS_ZERO 0x01
-#define IEEE754_CLASS_DNORM 0x02
-#define IEEE754_CLASS_INF 0x03
-#define IEEE754_CLASS_SNAN 0x04
-#define IEEE754_CLASS_QNAN 0x05
+enum {
+ IEEE754_CLASS_NORM = 0x00,
+ IEEE754_CLASS_ZERO = 0x01,
+ IEEE754_CLASS_DNORM = 0x02,
+ IEEE754_CLASS_INF = 0x03,
+ IEEE754_CLASS_SNAN = 0x04,
+ IEEE754_CLASS_QNAN = 0x05,
+};
/* exception numbers */
#define IEEE754_INEXACT 0x01
@@ -219,114 +126,84 @@ ieee754dp ieee754dp_sqrt(ieee754dp x);
#define IEEE754_CGT 0x04
#define IEEE754_CUN 0x08
-/* rounding mode
-*/
-#define IEEE754_RN 0 /* round to nearest */
-#define IEEE754_RZ 1 /* round toward zero */
-#define IEEE754_RD 2 /* round toward -Infinity */
-#define IEEE754_RU 3 /* round toward +Infinity */
-
-/* other naming */
-#define IEEE754_RM IEEE754_RD
-#define IEEE754_RP IEEE754_RU
-
/* "normal" comparisons
*/
-static inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y)
{
return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);
}
-static inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_ne(union ieee754sp x, union ieee754sp y)
{
return ieee754sp_cmp(x, y,
IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
}
-static inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_lt(union ieee754sp x, union ieee754sp y)
{
return ieee754sp_cmp(x, y, IEEE754_CLT, 0);
}
-static inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_le(union ieee754sp x, union ieee754sp y)
{
return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
}
-static inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_gt(union ieee754sp x, union ieee754sp y)
{
return ieee754sp_cmp(x, y, IEEE754_CGT, 0);
}
-static inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_ge(union ieee754sp x, union ieee754sp y)
{
return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
}
-static inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_eq(union ieee754dp x, union ieee754dp y)
{
return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);
}
-static inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_ne(union ieee754dp x, union ieee754dp y)
{
return ieee754dp_cmp(x, y,
IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
}
-static inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_lt(union ieee754dp x, union ieee754dp y)
{
return ieee754dp_cmp(x, y, IEEE754_CLT, 0);
}
-static inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_le(union ieee754dp x, union ieee754dp y)
{
return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
}
-static inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_gt(union ieee754dp x, union ieee754dp y)
{
return ieee754dp_cmp(x, y, IEEE754_CGT, 0);
}
-static inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_ge(union ieee754dp x, union ieee754dp y)
{
return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
}
-
-/*
- * Like strtod
- */
-ieee754dp ieee754dp_fstr(const char *s, char **endp);
-char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
-
-
/*
* The control status register
*/
struct _ieee754_csr {
-#ifdef __BIG_ENDIAN
- unsigned pad0:7;
- unsigned nod:1; /* set 1 for no denormalised numbers */
- unsigned c:1; /* condition */
- unsigned pad1:5;
- unsigned cx:6; /* exceptions this operation */
- unsigned mx:5; /* exception enable mask */
- unsigned sx:5; /* exceptions total */
- unsigned rm:2; /* current rounding mode */
-#endif
-#ifdef __LITTLE_ENDIAN
- unsigned rm:2; /* current rounding mode */
- unsigned sx:5; /* exceptions total */
- unsigned mx:5; /* exception enable mask */
- unsigned cx:6; /* exceptions this operation */
- unsigned pad1:5;
- unsigned c:1; /* condition */
- unsigned nod:1; /* set 1 for no denormalised numbers */
- unsigned pad0:7;
-#endif
+ __BITFIELD_FIELD(unsigned pad0:7,
+ __BITFIELD_FIELD(unsigned nod:1, /* set 1 for no denormalised numbers */
+ __BITFIELD_FIELD(unsigned c:1, /* condition */
+ __BITFIELD_FIELD(unsigned pad1:5,
+ __BITFIELD_FIELD(unsigned cx:6, /* exceptions this operation */
+ __BITFIELD_FIELD(unsigned mx:5, /* exception enable mask */
+ __BITFIELD_FIELD(unsigned sx:5, /* exceptions total */
+ __BITFIELD_FIELD(unsigned rm:2, /* current rounding mode */
+ ;))))))))
};
#define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.fcr31))
@@ -377,8 +254,8 @@ static inline int ieee754_sxtest(unsigned n)
}
/* debugging */
-ieee754sp ieee754sp_dump(char *s, ieee754sp x);
-ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+union ieee754sp ieee754sp_dump(char *s, union ieee754sp x);
+union ieee754dp ieee754dp_dump(char *s, union ieee754dp x);
#define IEEE754_SPCVAL_PZERO 0
#define IEEE754_SPCVAL_NZERO 1
@@ -398,10 +275,10 @@ ieee754dp ieee754dp_dump(char *s, ieee754dp x);
#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */
#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */
-extern const struct ieee754dp_konst __ieee754dp_spcvals[];
-extern const struct ieee754sp_konst __ieee754sp_spcvals[];
-#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
-#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+extern const union ieee754dp __ieee754dp_spcvals[];
+extern const union ieee754sp __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const union ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const union ieee754sp *)__ieee754sp_spcvals)
/*
* Return infinity with given sign
@@ -431,28 +308,15 @@ extern const struct ieee754sp_konst __ieee754sp_spcvals[];
/*
* Indefinite integer value
*/
-#define ieee754si_indef() INT_MAX
-#ifdef LONG_LONG_MAX
-#define ieee754di_indef() LONG_LONG_MAX
-#else
-#define ieee754di_indef() ((s64)(~0ULL>>1))
-#endif
-
-/* IEEE exception context, passed to handler */
-struct ieee754xctx {
- const char *op; /* operation name */
- int rt; /* result type */
- union {
- ieee754sp sp; /* single precision */
- ieee754dp dp; /* double precision */
-#ifdef IEEE854_XP
- ieee754xp xp; /* extended precision */
-#endif
- int si; /* standard signed integer (32bits) */
- s64 di; /* extended signed integer (64bits) */
- } rv; /* default result format implied by op */
- va_list ap;
-};
+static inline int ieee754si_indef(void)
+{
+ return INT_MAX;
+}
+
+static inline s64 ieee754di_indef(void)
+{
+ return S64_MAX;
+}
/* result types for xctx.rt */
#define IEEE754_RT_SP 0
@@ -461,8 +325,6 @@ struct ieee754xctx {
#define IEEE754_RT_SI 3
#define IEEE754_RT_DI 4
-extern void ieee754_xcpt(struct ieee754xctx *xcp);
-
/* compat */
#define ieee754dp_fix(x) ieee754dp_tint(x)
#define ieee754sp_fix(x) ieee754sp_tint(x)
diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c
index 9599bdd3258..a04e8a7e5ac 100644
--- a/arch/mips/math-emu/ieee754d.c
+++ b/arch/mips/math-emu/ieee754d.c
@@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Nov 7, 2000
* Modified to build and operate in Linux kernel environment.
@@ -25,38 +25,13 @@
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
*/
-#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/printk.h>
#include "ieee754.h"
+#include "ieee754sp.h"
+#include "ieee754dp.h"
-#define DP_EBIAS 1023
-#define DP_EMIN (-1022)
-#define DP_EMAX 1023
-#define DP_FBITS 52
-
-#define SP_EBIAS 127
-#define SP_EMIN (-126)
-#define SP_EMAX 127
-#define SP_FBITS 23
-
-#define DP_MBIT(x) ((u64)1 << (x))
-#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS)
-#define DP_SIGN_BIT DP_MBIT(63)
-
-
-#define SP_MBIT(x) ((u32)1 << (x))
-#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS)
-#define SP_SIGN_BIT SP_MBIT(31)
-
-
-#define SPSIGN(sp) (sp.parts.sign)
-#define SPBEXP(sp) (sp.parts.bexp)
-#define SPMANT(sp) (sp.parts.mant)
-
-#define DPSIGN(dp) (dp.parts.sign)
-#define DPBEXP(dp) (dp.parts.bexp)
-#define DPMANT(dp) (dp.parts.mant)
-
-ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+union ieee754dp ieee754dp_dump(char *m, union ieee754dp x)
{
int i;
@@ -96,7 +71,7 @@ ieee754dp ieee754dp_dump(char *m, ieee754dp x)
return x;
}
-ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+union ieee754sp ieee754sp_dump(char *m, union ieee754sp x)
{
int i;
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c
index 068e56be8de..fd134675fc2 100644
--- a/arch/mips/math-emu/ieee754dp.c
+++ b/arch/mips/math-emu/ieee754dp.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,104 +16,68 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <linux/compiler.h>
#include "ieee754dp.h"
-int ieee754dp_class(ieee754dp x)
+int ieee754dp_class(union ieee754dp x)
{
COMPXDP;
EXPLODEXDP;
return xc;
}
-int ieee754dp_isnan(ieee754dp x)
+int ieee754dp_isnan(union ieee754dp x)
{
return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
}
-int ieee754dp_issnan(ieee754dp x)
+static inline int ieee754dp_issnan(union ieee754dp x)
{
assert(ieee754dp_isnan(x));
- return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1));
+ return ((DPMANT(x) & DP_MBIT(DP_FBITS-1)) == DP_MBIT(DP_FBITS-1));
}
-ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
-{
- struct ieee754xctx ax;
- if (!TSTX())
- return r;
-
- ax.op = op;
- ax.rt = IEEE754_RT_DP;
- ax.rv.dp = r;
- va_start(ax.ap, op);
- ieee754_xcpt(&ax);
- va_end(ax.ap);
- return ax.rv.dp;
-}
-
-ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)
{
- struct ieee754xctx ax;
-
assert(ieee754dp_isnan(r));
if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */
return r;
- if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
+ if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {
/* not enabled convert to a quiet NaN */
- DPMANT(r) &= (~DP_MBIT(DP_MBITS-1));
+ DPMANT(r) &= (~DP_MBIT(DP_FBITS-1));
if (ieee754dp_isnan(r))
return r;
else
return ieee754dp_indef();
}
- ax.op = op;
- ax.rt = 0;
- ax.rv.dp = r;
- va_start(ax.ap, op);
- ieee754_xcpt(&ax);
- va_end(ax.ap);
- return ax.rv.dp;
+ return r;
}
-ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
-{
- assert(ieee754dp_isnan(x));
- assert(ieee754dp_isnan(y));
-
- if (DPMANT(x) > DPMANT(y))
- return x;
- else
- return y;
-}
-
-
-static u64 get_rounding(int sn, u64 xm)
+static u64 ieee754dp_get_rounding(int sn, u64 xm)
{
/* inexact must round of 3 bits
*/
if (xm & (DP_MBIT(3) - 1)) {
switch (ieee754_csr.rm) {
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
break;
- case IEEE754_RN:
+ case FPU_CSR_RN:
xm += 0x3 + ((xm >> 3) & 1);
/* xm += (xm&0x8)?0x4:0x3 */
break;
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if (!sn) /* ?? */
xm += 0x8;
break;
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if (sn) /* ?? */
xm += 0x8;
break;
@@ -130,11 +92,11 @@ static u64 get_rounding(int sn, u64 xm)
* xe is an unbiased exponent
* xm is 3bit extended precision value.
*/
-ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
+union ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
{
assert(xm); /* we don't gen exact zeros (probably should) */
- assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */
+ assert((xm >> (DP_FBITS + 1 + 3)) == 0); /* no execess */
assert(xm & (DP_HIDDEN_BIT << 3));
if (xe < DP_EMIN) {
@@ -142,32 +104,32 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
int es = DP_EMIN - xe;
if (ieee754_csr.nod) {
- SETCX(IEEE754_UNDERFLOW);
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_UNDERFLOW);
+ ieee754_setcx(IEEE754_INEXACT);
switch(ieee754_csr.rm) {
- case IEEE754_RN:
- case IEEE754_RZ:
+ case FPU_CSR_RN:
+ case FPU_CSR_RZ:
return ieee754dp_zero(sn);
- case IEEE754_RU: /* toward +Infinity */
- if(sn == 0)
+ case FPU_CSR_RU: /* toward +Infinity */
+ if (sn == 0)
return ieee754dp_min(0);
else
return ieee754dp_zero(1);
- case IEEE754_RD: /* toward -Infinity */
- if(sn == 0)
+ case FPU_CSR_RD: /* toward -Infinity */
+ if (sn == 0)
return ieee754dp_zero(0);
else
return ieee754dp_min(1);
}
}
- if (xe == DP_EMIN - 1
- && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3))
+ if (xe == DP_EMIN - 1 &&
+ ieee754dp_get_rounding(sn, xm) >> (DP_FBITS + 1 + 3))
{
/* Not tiny after rounding */
- SETCX(IEEE754_INEXACT);
- xm = get_rounding(sn, xm);
+ ieee754_setcx(IEEE754_INEXACT);
+ xm = ieee754dp_get_rounding(sn, xm);
xm >>= 1;
/* Clear grs bits */
xm &= ~(DP_MBIT(3) - 1);
@@ -183,17 +145,17 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
}
}
if (xm & (DP_MBIT(3) - 1)) {
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_INEXACT);
if ((xm & (DP_HIDDEN_BIT << 3)) == 0) {
- SETCX(IEEE754_UNDERFLOW);
+ ieee754_setcx(IEEE754_UNDERFLOW);
}
/* inexact must round of 3 bits
*/
- xm = get_rounding(sn, xm);
+ xm = ieee754dp_get_rounding(sn, xm);
/* adjust exponent for rounding add overflowing
*/
- if (xm >> (DP_MBITS + 3 + 1)) {
+ if (xm >> (DP_FBITS + 3 + 1)) {
/* add causes mantissa overflow */
xm >>= 1;
xe++;
@@ -202,24 +164,24 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
/* strip grs bits */
xm >>= 3;
- assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
+ assert((xm >> (DP_FBITS + 1)) == 0); /* no execess */
assert(xe >= DP_EMIN);
if (xe > DP_EMAX) {
- SETCX(IEEE754_OVERFLOW);
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_OVERFLOW);
+ ieee754_setcx(IEEE754_INEXACT);
/* -O can be table indexed by (rm,sn) */
switch (ieee754_csr.rm) {
- case IEEE754_RN:
+ case FPU_CSR_RN:
return ieee754dp_inf(sn);
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
return ieee754dp_max(sn);
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if (sn == 0)
return ieee754dp_inf(0);
else
return ieee754dp_max(1);
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if (sn == 0)
return ieee754dp_max(0);
else
@@ -232,10 +194,10 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
/* we underflow (tiny/zero) */
assert(xe == DP_EMIN);
if (ieee754_csr.mx & IEEE754_UNDERFLOW)
- SETCX(IEEE754_UNDERFLOW);
+ ieee754_setcx(IEEE754_UNDERFLOW);
return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
} else {
- assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
+ assert((xm >> (DP_FBITS + 1)) == 0); /* no execess */
assert(xm & DP_HIDDEN_BIT);
return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h
index f139c724c59..61fd6fd3135 100644
--- a/arch/mips/math-emu/ieee754dp.h
+++ b/arch/mips/math-emu/ieee754dp.h
@@ -6,8 +6,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -19,64 +17,66 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <linux/compiler.h>
#include "ieee754int.h"
#define assert(expr) ((void)0)
+#define DP_EBIAS 1023
+#define DP_EMIN (-1022)
+#define DP_EMAX 1023
+#define DP_FBITS 52
+#define DP_MBITS 52
+
+#define DP_MBIT(x) ((u64)1 << (x))
+#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS)
+#define DP_SIGN_BIT DP_MBIT(63)
+
+#define DPSIGN(dp) (dp.sign)
+#define DPBEXP(dp) (dp.bexp)
+#define DPMANT(dp) (dp.mant)
+
+static inline int ieee754dp_finite(union ieee754dp x)
+{
+ return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
+}
+
/* 3bit extended double precision sticky right shift */
#define XDPSRS(v,rs) \
- ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+ ((rs > (DP_FBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
#define XDPSRSX1() \
- (xe++, (xm = (xm >> 1) | (xm & 1)))
+ (xe++, (xm = (xm >> 1) | (xm & 1)))
#define XDPSRS1(v) \
- (((v) >> 1) | ((v) & 1))
+ (((v) >> 1) | ((v) & 1))
/* convert denormal to normalized with extended exponent */
#define DPDNORMx(m,e) \
- while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+ while ((m >> DP_FBITS) == 0) { m <<= 1; e--; }
#define DPDNORMX DPDNORMx(xm, xe)
#define DPDNORMY DPDNORMx(ym, ye)
-static inline ieee754dp builddp(int s, int bx, u64 m)
+static inline union ieee754dp builddp(int s, int bx, u64 m)
{
- ieee754dp r;
+ union ieee754dp r;
assert((s) == 0 || (s) == 1);
assert((bx) >= DP_EMIN - 1 + DP_EBIAS
&& (bx) <= DP_EMAX + 1 + DP_EBIAS);
- assert(((m) >> DP_MBITS) == 0);
+ assert(((m) >> DP_FBITS) == 0);
- r.parts.sign = s;
- r.parts.bexp = bx;
- r.parts.mant = m;
- return r;
-}
+ r.sign = s;
+ r.bexp = bx;
+ r.mant = m;
-extern int ieee754dp_isnan(ieee754dp);
-extern int ieee754dp_issnan(ieee754dp);
-extern int ieee754si_xcpt(int, const char *, ...);
-extern s64 ieee754di_xcpt(s64, const char *, ...);
-extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
-extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
-extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
-extern ieee754dp ieee754dp_format(int, int, u64);
-
-
-#define DPNORMRET2(s, e, m, name, a0, a1) \
-{ \
- ieee754dp V = ieee754dp_format(s, e, m); \
- if(TSTX()) \
- return ieee754dp_xcpt(V, name, a0, a1); \
- else \
- return V; \
+ return r;
}
-#define DPNORMRET1(s, e, m, name, a0) DPNORMRET2(s, e, m, name, a0, a0)
+extern int ieee754dp_isnan(union ieee754dp);
+extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp);
+extern union ieee754dp ieee754dp_format(int, int, u64);
diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h
index 4b6c6fb3530..f0365bb8674 100644
--- a/arch/mips/math-emu/ieee754int.h
+++ b/arch/mips/math-emu/ieee754int.h
@@ -6,8 +6,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -19,146 +17,125 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
+#ifndef __IEEE754INT_H
+#define __IEEE754INT_H
#include "ieee754.h"
-#define DP_EBIAS 1023
-#define DP_EMIN (-1022)
-#define DP_EMAX 1023
-#define DP_MBITS 52
-
-#define SP_EBIAS 127
-#define SP_EMIN (-126)
-#define SP_EMAX 127
-#define SP_MBITS 23
-
-#define DP_MBIT(x) ((u64)1 << (x))
-#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS)
-#define DP_SIGN_BIT DP_MBIT(63)
-
-#define SP_MBIT(x) ((u32)1 << (x))
-#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS)
-#define SP_SIGN_BIT SP_MBIT(31)
-
-
-#define SPSIGN(sp) (sp.parts.sign)
-#define SPBEXP(sp) (sp.parts.bexp)
-#define SPMANT(sp) (sp.parts.mant)
-
-#define DPSIGN(dp) (dp.parts.sign)
-#define DPBEXP(dp) (dp.parts.bexp)
-#define DPMANT(dp) (dp.parts.mant)
-
#define CLPAIR(x, y) ((x)*6+(y))
-#define CLEARCX \
- (ieee754_csr.cx = 0)
-
-#define SETCX(x) \
- (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x))
+static inline void ieee754_clearcx(void)
+{
+ ieee754_csr.cx = 0;
+}
-#define SETANDTESTCX(x) \
- (SETCX(x), ieee754_csr.mx & (x))
+static inline void ieee754_setcx(const unsigned int flags)
+{
+ ieee754_csr.cx |= flags;
+ ieee754_csr.sx |= flags;
+}
-#define TSTX() \
- (ieee754_csr.cx & ieee754_csr.mx)
+static inline int ieee754_setandtestcx(const unsigned int x)
+{
+ ieee754_setcx(x);
+ return ieee754_csr.mx & x;
+}
#define COMPXSP \
- unsigned xm; int xe; int xs __maybe_unused; int xc
+ unsigned xm; int xe; int xs __maybe_unused; int xc
#define COMPYSP \
- unsigned ym; int ye; int ys; int yc
-
-#define EXPLODESP(v, vc, vs, ve, vm) \
-{\
- vs = SPSIGN(v);\
- ve = SPBEXP(v);\
- vm = SPMANT(v);\
- if(ve == SP_EMAX+1+SP_EBIAS){\
- if(vm == 0)\
- vc = IEEE754_CLASS_INF;\
- else if(vm & SP_MBIT(SP_MBITS-1)) \
- vc = IEEE754_CLASS_SNAN;\
- else \
- vc = IEEE754_CLASS_QNAN;\
- } else if(ve == SP_EMIN-1+SP_EBIAS) {\
- if(vm) {\
- ve = SP_EMIN;\
- vc = IEEE754_CLASS_DNORM;\
- } else\
- vc = IEEE754_CLASS_ZERO;\
- } else {\
- ve -= SP_EBIAS;\
- vm |= SP_HIDDEN_BIT;\
- vc = IEEE754_CLASS_NORM;\
- }\
+ unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v, vc, vs, ve, vm) \
+{ \
+ vs = SPSIGN(v); \
+ ve = SPBEXP(v); \
+ vm = SPMANT(v); \
+ if (ve == SP_EMAX+1+SP_EBIAS) { \
+ if (vm == 0) \
+ vc = IEEE754_CLASS_INF; \
+ else if (vm & SP_MBIT(SP_FBITS-1)) \
+ vc = IEEE754_CLASS_SNAN; \
+ else \
+ vc = IEEE754_CLASS_QNAN; \
+ } else if (ve == SP_EMIN-1+SP_EBIAS) { \
+ if (vm) { \
+ ve = SP_EMIN; \
+ vc = IEEE754_CLASS_DNORM; \
+ } else \
+ vc = IEEE754_CLASS_ZERO; \
+ } else { \
+ ve -= SP_EBIAS; \
+ vm |= SP_HIDDEN_BIT; \
+ vc = IEEE754_CLASS_NORM; \
+ } \
}
#define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm)
#define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym)
#define COMPXDP \
-u64 xm; int xe; int xs __maybe_unused; int xc
+ u64 xm; int xe; int xs __maybe_unused; int xc
#define COMPYDP \
-u64 ym; int ye; int ys; int yc
-
-#define EXPLODEDP(v, vc, vs, ve, vm) \
-{\
- vm = DPMANT(v);\
- vs = DPSIGN(v);\
- ve = DPBEXP(v);\
- if(ve == DP_EMAX+1+DP_EBIAS){\
- if(vm == 0)\
- vc = IEEE754_CLASS_INF;\
- else if(vm & DP_MBIT(DP_MBITS-1)) \
- vc = IEEE754_CLASS_SNAN;\
- else \
- vc = IEEE754_CLASS_QNAN;\
- } else if(ve == DP_EMIN-1+DP_EBIAS) {\
- if(vm) {\
- ve = DP_EMIN;\
- vc = IEEE754_CLASS_DNORM;\
- } else\
- vc = IEEE754_CLASS_ZERO;\
- } else {\
- ve -= DP_EBIAS;\
- vm |= DP_HIDDEN_BIT;\
- vc = IEEE754_CLASS_NORM;\
- }\
+ u64 ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v, vc, vs, ve, vm) \
+{ \
+ vm = DPMANT(v); \
+ vs = DPSIGN(v); \
+ ve = DPBEXP(v); \
+ if (ve == DP_EMAX+1+DP_EBIAS) { \
+ if (vm == 0) \
+ vc = IEEE754_CLASS_INF; \
+ else if (vm & DP_MBIT(DP_FBITS-1)) \
+ vc = IEEE754_CLASS_SNAN; \
+ else \
+ vc = IEEE754_CLASS_QNAN; \
+ } else if (ve == DP_EMIN-1+DP_EBIAS) { \
+ if (vm) { \
+ ve = DP_EMIN; \
+ vc = IEEE754_CLASS_DNORM; \
+ } else \
+ vc = IEEE754_CLASS_ZERO; \
+ } else { \
+ ve -= DP_EBIAS; \
+ vm |= DP_HIDDEN_BIT; \
+ vc = IEEE754_CLASS_NORM; \
+ } \
}
#define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm)
#define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym)
-#define FLUSHDP(v, vc, vs, ve, vm) \
- if(vc==IEEE754_CLASS_DNORM) {\
- if(ieee754_csr.nod) {\
- SETCX(IEEE754_INEXACT);\
- vc = IEEE754_CLASS_ZERO;\
- ve = DP_EMIN-1+DP_EBIAS;\
- vm = 0;\
- v = ieee754dp_zero(vs);\
- }\
+#define FLUSHDP(v, vc, vs, ve, vm) \
+ if (vc==IEEE754_CLASS_DNORM) { \
+ if (ieee754_csr.nod) { \
+ ieee754_setcx(IEEE754_INEXACT); \
+ vc = IEEE754_CLASS_ZERO; \
+ ve = DP_EMIN-1+DP_EBIAS; \
+ vm = 0; \
+ v = ieee754dp_zero(vs); \
+ } \
}
-#define FLUSHSP(v, vc, vs, ve, vm) \
- if(vc==IEEE754_CLASS_DNORM) {\
- if(ieee754_csr.nod) {\
- SETCX(IEEE754_INEXACT);\
- vc = IEEE754_CLASS_ZERO;\
- ve = SP_EMIN-1+SP_EBIAS;\
- vm = 0;\
- v = ieee754sp_zero(vs);\
- }\
+#define FLUSHSP(v, vc, vs, ve, vm) \
+ if (vc==IEEE754_CLASS_DNORM) { \
+ if (ieee754_csr.nod) { \
+ ieee754_setcx(IEEE754_INEXACT); \
+ vc = IEEE754_CLASS_ZERO; \
+ ve = SP_EMIN-1+SP_EBIAS; \
+ vm = 0; \
+ v = ieee754sp_zero(vs); \
+ } \
}
#define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm)
#define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym)
#define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm)
#define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym)
+
+#endif /* __IEEE754INT_H */
diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c
deleted file mode 100644
index 24190f3c9dd..00000000000
--- a/arch/mips/math-emu/ieee754m.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * floor, trunc, ceil
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754.h"
-
-ieee754dp ieee754dp_floor(ieee754dp x)
-{
- ieee754dp i;
-
- if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
- return ieee754dp_sub(i, ieee754dp_one(0));
- else
- return i;
-}
-
-ieee754dp ieee754dp_ceil(ieee754dp x)
-{
- ieee754dp i;
-
- if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
- return ieee754dp_add(i, ieee754dp_one(0));
- else
- return i;
-}
-
-ieee754dp ieee754dp_trunc(ieee754dp x)
-{
- ieee754dp i;
-
- (void) ieee754dp_modf(x, &i);
- return i;
-}
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c
index 15d1e36cfe6..d348efe9144 100644
--- a/arch/mips/math-emu/ieee754sp.c
+++ b/arch/mips/math-emu/ieee754sp.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,105 +16,68 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <linux/compiler.h>
#include "ieee754sp.h"
-int ieee754sp_class(ieee754sp x)
+int ieee754sp_class(union ieee754sp x)
{
COMPXSP;
EXPLODEXSP;
return xc;
}
-int ieee754sp_isnan(ieee754sp x)
+int ieee754sp_isnan(union ieee754sp x)
{
return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
}
-int ieee754sp_issnan(ieee754sp x)
+static inline int ieee754sp_issnan(union ieee754sp x)
{
assert(ieee754sp_isnan(x));
- return (SPMANT(x) & SP_MBIT(SP_MBITS-1));
+ return (SPMANT(x) & SP_MBIT(SP_FBITS-1));
}
-ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
-{
- struct ieee754xctx ax;
-
- if (!TSTX())
- return r;
-
- ax.op = op;
- ax.rt = IEEE754_RT_SP;
- ax.rv.sp = r;
- va_start(ax.ap, op);
- ieee754_xcpt(&ax);
- va_end(ax.ap);
- return ax.rv.sp;
-}
-
-ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
{
- struct ieee754xctx ax;
-
assert(ieee754sp_isnan(r));
if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */
return r;
- if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
+ if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {
/* not enabled convert to a quiet NaN */
- SPMANT(r) &= (~SP_MBIT(SP_MBITS-1));
+ SPMANT(r) &= (~SP_MBIT(SP_FBITS-1));
if (ieee754sp_isnan(r))
return r;
else
return ieee754sp_indef();
}
- ax.op = op;
- ax.rt = 0;
- ax.rv.sp = r;
- va_start(ax.ap, op);
- ieee754_xcpt(&ax);
- va_end(ax.ap);
- return ax.rv.sp;
-}
-
-ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
-{
- assert(ieee754sp_isnan(x));
- assert(ieee754sp_isnan(y));
-
- if (SPMANT(x) > SPMANT(y))
- return x;
- else
- return y;
+ return r;
}
-
-static unsigned get_rounding(int sn, unsigned xm)
+static unsigned ieee754sp_get_rounding(int sn, unsigned xm)
{
/* inexact must round of 3 bits
*/
if (xm & (SP_MBIT(3) - 1)) {
switch (ieee754_csr.rm) {
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
break;
- case IEEE754_RN:
+ case FPU_CSR_RN:
xm += 0x3 + ((xm >> 3) & 1);
/* xm += (xm&0x8)?0x4:0x3 */
break;
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if (!sn) /* ?? */
xm += 0x8;
break;
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if (sn) /* ?? */
xm += 0x8;
break;
@@ -131,11 +92,11 @@ static unsigned get_rounding(int sn, unsigned xm)
* xe is an unbiased exponent
* xm is 3bit extended precision value.
*/
-ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
{
assert(xm); /* we don't gen exact zeros (probably should) */
- assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */
+ assert((xm >> (SP_FBITS + 1 + 3)) == 0); /* no execess */
assert(xm & (SP_HIDDEN_BIT << 3));
if (xe < SP_EMIN) {
@@ -143,38 +104,37 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
int es = SP_EMIN - xe;
if (ieee754_csr.nod) {
- SETCX(IEEE754_UNDERFLOW);
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_UNDERFLOW);
+ ieee754_setcx(IEEE754_INEXACT);
switch(ieee754_csr.rm) {
- case IEEE754_RN:
- case IEEE754_RZ:
+ case FPU_CSR_RN:
+ case FPU_CSR_RZ:
return ieee754sp_zero(sn);
- case IEEE754_RU: /* toward +Infinity */
- if(sn == 0)
+ case FPU_CSR_RU: /* toward +Infinity */
+ if (sn == 0)
return ieee754sp_min(0);
else
return ieee754sp_zero(1);
- case IEEE754_RD: /* toward -Infinity */
- if(sn == 0)
+ case FPU_CSR_RD: /* toward -Infinity */
+ if (sn == 0)
return ieee754sp_zero(0);
else
return ieee754sp_min(1);
}
}
- if (xe == SP_EMIN - 1
- && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3))
+ if (xe == SP_EMIN - 1 &&
+ ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3))
{
/* Not tiny after rounding */
- SETCX(IEEE754_INEXACT);
- xm = get_rounding(sn, xm);
+ ieee754_setcx(IEEE754_INEXACT);
+ xm = ieee754sp_get_rounding(sn, xm);
xm >>= 1;
/* Clear grs bits */
xm &= ~(SP_MBIT(3) - 1);
xe++;
- }
- else {
+ } else {
/* sticky right shift es bits
*/
SPXSRSXn(es);
@@ -183,17 +143,17 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
}
}
if (xm & (SP_MBIT(3) - 1)) {
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_INEXACT);
if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
- SETCX(IEEE754_UNDERFLOW);
+ ieee754_setcx(IEEE754_UNDERFLOW);
}
/* inexact must round of 3 bits
*/
- xm = get_rounding(sn, xm);
+ xm = ieee754sp_get_rounding(sn, xm);
/* adjust exponent for rounding add overflowing
*/
- if (xm >> (SP_MBITS + 1 + 3)) {
+ if (xm >> (SP_FBITS + 1 + 3)) {
/* add causes mantissa overflow */
xm >>= 1;
xe++;
@@ -202,24 +162,24 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
/* strip grs bits */
xm >>= 3;
- assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
+ assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */
assert(xe >= SP_EMIN);
if (xe > SP_EMAX) {
- SETCX(IEEE754_OVERFLOW);
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_OVERFLOW);
+ ieee754_setcx(IEEE754_INEXACT);
/* -O can be table indexed by (rm,sn) */
switch (ieee754_csr.rm) {
- case IEEE754_RN:
+ case FPU_CSR_RN:
return ieee754sp_inf(sn);
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
return ieee754sp_max(sn);
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if (sn == 0)
return ieee754sp_inf(0);
else
return ieee754sp_max(1);
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if (sn == 0)
return ieee754sp_max(0);
else
@@ -232,10 +192,10 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
/* we underflow (tiny/zero) */
assert(xe == SP_EMIN);
if (ieee754_csr.mx & IEEE754_UNDERFLOW)
- SETCX(IEEE754_UNDERFLOW);
+ ieee754_setcx(IEEE754_UNDERFLOW);
return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
} else {
- assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
+ assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */
assert(xm & SP_HIDDEN_BIT);
return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h
index 754fd54649b..ad268e33231 100644
--- a/arch/mips/math-emu/ieee754sp.h
+++ b/arch/mips/math-emu/ieee754sp.h
@@ -6,8 +6,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -19,70 +17,71 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <linux/compiler.h>
#include "ieee754int.h"
#define assert(expr) ((void)0)
+#define SP_EBIAS 127
+#define SP_EMIN (-126)
+#define SP_EMAX 127
+#define SP_FBITS 23
+#define SP_MBITS 23
+
+#define SP_MBIT(x) ((u32)1 << (x))
+#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS)
+#define SP_SIGN_BIT SP_MBIT(31)
+
+#define SPSIGN(sp) (sp.sign)
+#define SPBEXP(sp) (sp.bexp)
+#define SPMANT(sp) (sp.mant)
+
+static inline int ieee754sp_finite(union ieee754sp x)
+{
+ return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
+}
+
/* 3bit extended single precision sticky right shift */
-#define SPXSRSXn(rs) \
- (xe += rs, \
- xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+#define SPXSRSXn(rs) \
+ (xe += rs, \
+ xm = (rs > (SP_FBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
#define SPXSRSX1() \
- (xe++, (xm = (xm >> 1) | (xm & 1)))
+ (xe++, (xm = (xm >> 1) | (xm & 1)))
-#define SPXSRSYn(rs) \
- (ye+=rs, \
- ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+#define SPXSRSYn(rs) \
+ (ye+=rs, \
+ ym = (rs > (SP_FBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
#define SPXSRSY1() \
- (ye++, (ym = (ym >> 1) | (ym & 1)))
+ (ye++, (ym = (ym >> 1) | (ym & 1)))
/* convert denormal to normalized with extended exponent */
#define SPDNORMx(m,e) \
- while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+ while ((m >> SP_FBITS) == 0) { m <<= 1; e--; }
#define SPDNORMX SPDNORMx(xm, xe)
#define SPDNORMY SPDNORMx(ym, ye)
-static inline ieee754sp buildsp(int s, int bx, unsigned m)
+static inline union ieee754sp buildsp(int s, int bx, unsigned m)
{
- ieee754sp r;
+ union ieee754sp r;
assert((s) == 0 || (s) == 1);
assert((bx) >= SP_EMIN - 1 + SP_EBIAS
&& (bx) <= SP_EMAX + 1 + SP_EBIAS);
- assert(((m) >> SP_MBITS) == 0);
+ assert(((m) >> SP_FBITS) == 0);
- r.parts.sign = s;
- r.parts.bexp = bx;
- r.parts.mant = m;
+ r.sign = s;
+ r.bexp = bx;
+ r.mant = m;
return r;
}
-extern int ieee754sp_isnan(ieee754sp);
-extern int ieee754sp_issnan(ieee754sp);
-extern int ieee754si_xcpt(int, const char *, ...);
-extern s64 ieee754di_xcpt(s64, const char *, ...);
-extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
-extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
-extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
-extern ieee754sp ieee754sp_format(int, int, unsigned);
-
-
-#define SPNORMRET2(s, e, m, name, a0, a1) \
-{ \
- ieee754sp V = ieee754sp_format(s, e, m); \
- if(TSTX()) \
- return ieee754sp_xcpt(V, name, a0, a1); \
- else \
- return V; \
-}
-
-#define SPNORMRET1(s, e, m, name, a0) SPNORMRET2(s, e, m, name, a0, a0)
+extern int ieee754sp_isnan(union ieee754sp);
+extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp);
+extern union ieee754sp ieee754sp_format(int, int, unsigned);
diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c
deleted file mode 100644
index 967167116ae..00000000000
--- a/arch/mips/math-emu/ieee754xcpt.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-/**************************************************************************
- * Nov 7, 2000
- * Added preprocessor hacks to map to Linux kernel diagnostics.
- *
- * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- *************************************************************************/
-
-#include <linux/kernel.h>
-#include "ieee754.h"
-
-/*
- * Very naff exception handler (you can plug in your own and
- * override this).
- */
-
-static const char *const rtnames[] = {
- "sp", "dp", "xp", "si", "di"
-};
-
-void ieee754_xcpt(struct ieee754xctx *xcp)
-{
- printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n",
- xcp->op, rtnames[xcp->rt]);
-}
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
deleted file mode 100644
index 1c586575fe1..00000000000
--- a/arch/mips/math-emu/kernel_linkage.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines corresponding to Linux kernel FP context
- * manipulation primitives for the Algorithmics MIPS
- * FPU Emulator
- */
-#include <linux/sched.h>
-#include <asm/processor.h>
-#include <asm/signal.h>
-#include <asm/uaccess.h>
-
-#include <asm/fpu.h>
-#include <asm/fpu_emulator.h>
-
-#define SIGNALLING_NAN 0x7ff800007ff80000LL
-
-void fpu_emulator_init_fpu(void)
-{
- static int first = 1;
- int i;
-
- if (first) {
- first = 0;
- printk("Algorithmics/MIPS FPU Emulator v1.5\n");
- }
-
- current->thread.fpu.fcr31 = 0;
- for (i = 0; i < 32; i++) {
- current->thread.fpu.fpr[i] = SIGNALLING_NAN;
- }
-}
-
-
-/*
- * Emulator context save/restore to/from a signal context
- * presumed to be on the user stack, and therefore accessed
- * with appropriate macros from uaccess.h
- */
-
-int fpu_emulator_save_context(struct sigcontext __user *sc)
-{
- int i;
- int err = 0;
-
- for (i = 0; i < 32; i++) {
- err |=
- __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
- }
- err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
- return err;
-}
-
-int fpu_emulator_restore_context(struct sigcontext __user *sc)
-{
- int i;
- int err = 0;
-
- for (i = 0; i < 32; i++) {
- err |=
- __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
- }
- err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
- return err;
-}
-
-#ifdef CONFIG_64BIT
-/*
- * This is the o32 version
- */
-
-int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
-{
- int i;
- int err = 0;
-
- for (i = 0; i < 32; i+=2) {
- err |=
- __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
- }
- err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
- return err;
-}
-
-int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
-{
- int i;
- int err = 0;
-
- for (i = 0; i < 32; i+=2) {
- err |=
- __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
- }
- err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
- return err;
-}
-#endif
diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c
new file mode 100644
index 00000000000..becdd63e14a
--- /dev/null
+++ b/arch/mips/math-emu/me-debugfs.c
@@ -0,0 +1,67 @@
+#include <linux/cpumask.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/types.h>
+#include <asm/fpu_emulator.h>
+#include <asm/local.h>
+
+DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+
+static int fpuemu_stat_get(void *data, u64 *val)
+{
+ int cpu;
+ unsigned long sum = 0;
+
+ for_each_online_cpu(cpu) {
+ struct mips_fpu_emulator_stats *ps;
+ local_t *pv;
+
+ ps = &per_cpu(fpuemustats, cpu);
+ pv = (void *)ps + (unsigned long)data;
+ sum += local_read(pv);
+ }
+ *val = sum;
+ return 0;
+}
+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;
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+ dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
+ if (!dir)
+ return -ENOMEM;
+
+#define FPU_EMU_STAT_OFFSET(m) \
+ offsetof(struct mips_fpu_emulator_stats, m)
+
+#define FPU_STAT_CREATE(m) \
+do { \
+ d = debugfs_create_file(#m , S_IRUGO, dir, \
+ (void *)FPU_EMU_STAT_OFFSET(m), \
+ &fops_fpuemu_stat); \
+ if (!d) \
+ return -ENOMEM; \
+} while (0)
+
+ FPU_STAT_CREATE(emulated);
+ FPU_STAT_CREATE(loads);
+ FPU_STAT_CREATE(stores);
+ FPU_STAT_CREATE(cp1ops);
+ FPU_STAT_CREATE(cp1xops);
+ FPU_STAT_CREATE(errors);
+ FPU_STAT_CREATE(ieee754_inexact);
+ FPU_STAT_CREATE(ieee754_underflow);
+ FPU_STAT_CREATE(ieee754_overflow);
+ FPU_STAT_CREATE(ieee754_zerodiv);
+ FPU_STAT_CREATE(ieee754_invalidop);
+
+ return 0;
+}
+__initcall(debugfs_fpuemu);
diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c
index c446e64637e..2d84d460cb6 100644
--- a/arch/mips/math-emu/sp_add.c
+++ b/arch/mips/math-emu/sp_add.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,23 +16,22 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
{
+ int s;
+
COMPXSP;
COMPYSP;
EXPLODEXSP;
EXPLODEYSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
FLUSHYSP;
@@ -51,8 +48,8 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -68,14 +65,14 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
return x;
- /* Infinity handling
- */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
if (xs == ys)
return x;
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
@@ -87,15 +84,14 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
return x;
- /* Zero handling
- */
-
+ /*
+ * Zero handling
+ */
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
else
- return ieee754sp_zero(ieee754_csr.rm ==
- IEEE754_RD);
+ return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
@@ -108,6 +104,8 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX;
+ /* FALL THROUGH */
+
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY;
break;
@@ -122,33 +120,38 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
assert(xm & SP_HIDDEN_BIT);
assert(ym & SP_HIDDEN_BIT);
- /* provide guard,round and stick bit space */
+ /*
+ * Provide guard, round and stick bit space.
+ */
xm <<= 3;
ym <<= 3;
if (xe > ye) {
- /* have to shift y fraction right to align
+ /*
+ * Have to shift y fraction right to align.
*/
- int s = xe - ye;
+ s = xe - ye;
SPXSRSYn(s);
} else if (ye > xe) {
- /* have to shift x fraction right to align
+ /*
+ * Have to shift x fraction right to align.
*/
- int s = ye - xe;
+ s = ye - xe;
SPXSRSXn(s);
}
assert(xe == ye);
assert(xe <= SP_EMAX);
if (xs == ys) {
- /* generate 28 bit result of adding two 27 bit numbers
- * leaving result in xm,xs,xe
+ /*
+ * Generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm, xs and xe.
*/
xm = xm + ym;
xe = xe;
xs = xs;
- if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+ if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */
SPXSRSX1();
}
} else {
@@ -162,15 +165,16 @@ ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
xs = ys;
}
if (xm == 0)
- return ieee754sp_zero(ieee754_csr.rm ==
- IEEE754_RD);
+ return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
- /* normalize in extended single precision */
- while ((xm >> (SP_MBITS + 3)) == 0) {
+ /*
+ * Normalize in extended single precision
+ */
+ while ((xm >> (SP_FBITS + 3)) == 0) {
xm <<= 1;
xe--;
}
-
}
- SPNORMRET2(xs, xe, xm, "add", x, y);
+
+ return ieee754sp_format(xs, xe, xm);
}
diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c
index 716cf37e246..addbccb2f55 100644
--- a/arch/mips/math-emu/sp_cmp.c
+++ b/arch/mips/math-emu/sp_cmp.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,16 +16,16 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig)
+int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig)
{
+ int vx;
+ int vy;
+
COMPXSP;
COMPYSP;
@@ -35,21 +33,21 @@ int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig)
EXPLODEYSP;
FLUSHXSP;
FLUSHYSP;
- CLEARCX; /* Even clear inexact flag here */
+ ieee754_clearcx(); /* Even clear inexact flag here */
if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
- SETCX(IEEE754_INVALID_OPERATION);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
if (cmp & IEEE754_CUN)
return 1;
if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
- if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
- return ieee754si_xcpt(0, "fcmpf", x);
+ if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
+ return 0;
}
return 0;
} else {
- int vx = x.bits;
- int vy = y.bits;
+ vx = x.bits;
+ vy = y.bits;
if (vx < 0)
vx = -vx ^ SP_SIGN_BIT;
diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c
index d7747928c95..721f317aa87 100644
--- a/arch/mips/math-emu/sp_div.c
+++ b/arch/mips/math-emu/sp_div.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,23 +16,24 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y)
{
+ unsigned rm;
+ int re;
+ unsigned bm;
+
COMPXSP;
COMPYSP;
EXPLODEXSP;
EXPLODEYSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
FLUSHYSP;
@@ -51,8 +50,8 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -68,12 +67,12 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
return x;
- /* Infinity handling
- */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
@@ -85,17 +84,17 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
return ieee754sp_inf(xs ^ ys);
- /* Zero handling
- */
-
+ /*
+ * Zero handling
+ */
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
- SETCX(IEEE754_ZERO_DIVIDE);
- return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
+ ieee754_setcx(IEEE754_ZERO_DIVIDE);
+ return ieee754sp_inf(xs ^ ys);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
@@ -122,35 +121,33 @@ ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
xm <<= 3;
ym <<= 3;
- {
- /* now the dirty work */
-
- unsigned rm = 0;
- int re = xe - ye;
- unsigned bm;
-
- for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
- if (xm >= ym) {
- xm -= ym;
- rm |= bm;
- if (xm == 0)
- break;
- }
- xm <<= 1;
- }
- rm <<= 1;
- if (xm)
- rm |= 1; /* have remainder, set sticky */
+ /* now the dirty work */
- assert(rm);
+ rm = 0;
+ re = xe - ye;
- /* normalise rm to rounding precision ?
- */
- while ((rm >> (SP_MBITS + 3)) == 0) {
- rm <<= 1;
- re--;
+ for (bm = SP_MBIT(SP_FBITS + 2); bm; bm >>= 1) {
+ if (xm >= ym) {
+ xm -= ym;
+ rm |= bm;
+ if (xm == 0)
+ break;
}
+ xm <<= 1;
+ }
+
+ rm <<= 1;
+ if (xm)
+ rm |= 1; /* have remainder, set sticky */
- SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+ assert(rm);
+
+ /* normalise rm to rounding precision ?
+ */
+ while ((rm >> (SP_FBITS + 3)) == 0) {
+ rm <<= 1;
+ re--;
}
+
+ return ieee754sp_format(xs == ys ? 0 : 1, re, rm);
}
diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c
index e1515aae016..1b266fb1697 100644
--- a/arch/mips/math-emu/sp_fdp.c
+++ b/arch/mips/math-emu/sp_fdp.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,59 +16,61 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
+#include "ieee754dp.h"
-ieee754sp ieee754sp_fdp(ieee754dp x)
+union ieee754sp ieee754sp_fdp(union ieee754dp x)
{
+ u32 rm;
+
COMPXDP;
- ieee754sp nan;
+ union ieee754sp nan;
EXPLODEXDP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXDP;
switch (xc) {
case IEEE754_CLASS_SNAN:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
+
case IEEE754_CLASS_QNAN:
nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32)
- (xm >> (DP_MBITS - SP_MBITS)));
+ (xm >> (DP_FBITS - SP_FBITS)));
if (!ieee754sp_isnan(nan))
nan = ieee754sp_indef();
- return ieee754sp_nanxcpt(nan, "fdp", x);
+ return ieee754sp_nanxcpt(nan);
+
case IEEE754_CLASS_INF:
return ieee754sp_inf(xs);
+
case IEEE754_CLASS_ZERO:
return ieee754sp_zero(xs);
+
case IEEE754_CLASS_DNORM:
/* can't possibly be sp representable */
- SETCX(IEEE754_UNDERFLOW);
- SETCX(IEEE754_INEXACT);
- if ((ieee754_csr.rm == IEEE754_RU && !xs) ||
- (ieee754_csr.rm == IEEE754_RD && xs))
- return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x);
- return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
+ ieee754_setcx(IEEE754_UNDERFLOW);
+ ieee754_setcx(IEEE754_INEXACT);
+ if ((ieee754_csr.rm == FPU_CSR_RU && !xs) ||
+ (ieee754_csr.rm == FPU_CSR_RD && xs))
+ return ieee754sp_mind(xs);
+ return ieee754sp_zero(xs);
+
case IEEE754_CLASS_NORM:
break;
}
- {
- u32 rm;
-
- /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift
- */
- rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
- ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
+ /*
+ * Convert from DP_FBITS to SP_FBITS+3 with sticky right shift.
+ */
+ rm = (xm >> (DP_FBITS - (SP_FBITS + 3))) |
+ ((xm << (64 - (DP_FBITS - (SP_FBITS + 3)))) != 0);
- SPNORMRET1(xs, xe, rm, "fdp", x);
- }
+ return ieee754sp_format(xs, xe, rm);
}
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c
index 9694d6c016c..d5d8495b2cc 100644
--- a/arch/mips/math-emu/sp_fint.c
+++ b/arch/mips/math-emu/sp_fint.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,21 +16,18 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-ieee754sp ieee754sp_fint(int x)
+union ieee754sp ieee754sp_fint(int x)
{
unsigned xm;
int xe;
int xs;
- CLEARCX;
+ ieee754_clearcx();
if (x == 0)
return ieee754sp_zero(0);
@@ -50,30 +45,21 @@ ieee754sp ieee754sp_fint(int x)
} else {
xm = x;
}
- xe = SP_MBITS + 3;
+ xe = SP_FBITS + 3;
- if (xm >> (SP_MBITS + 1 + 3)) {
+ if (xm >> (SP_FBITS + 1 + 3)) {
/* shunt out overflow bits
*/
- while (xm >> (SP_MBITS + 1 + 3)) {
+ while (xm >> (SP_FBITS + 1 + 3)) {
SPXSRSX1();
}
} else {
/* normalize in grs extended single precision
*/
- while ((xm >> (SP_MBITS + 3)) == 0) {
+ while ((xm >> (SP_FBITS + 3)) == 0) {
xm <<= 1;
xe--;
}
}
- SPNORMRET1(xs, xe, xm, "fint", x);
-}
-
-
-ieee754sp ieee754sp_funs(unsigned int u)
-{
- if ((int) u < 0)
- return ieee754sp_add(ieee754sp_1e31(),
- ieee754sp_fint(u & ~(1 << 31)));
- return ieee754sp_fint(u);
+ return ieee754sp_format(xs, xe, xm);
}
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c
index 16a651f2986..012e30ce758 100644
--- a/arch/mips/math-emu/sp_flong.c
+++ b/arch/mips/math-emu/sp_flong.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,21 +16,18 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-ieee754sp ieee754sp_flong(s64 x)
+union ieee754sp ieee754sp_flong(s64 x)
{
u64 xm; /* <--- need 64-bit mantissa temp */
int xe;
int xs;
- CLEARCX;
+ ieee754_clearcx();
if (x == 0)
return ieee754sp_zero(0);
@@ -50,29 +45,20 @@ ieee754sp ieee754sp_flong(s64 x)
} else {
xm = x;
}
- xe = SP_MBITS + 3;
+ xe = SP_FBITS + 3;
- if (xm >> (SP_MBITS + 1 + 3)) {
+ if (xm >> (SP_FBITS + 1 + 3)) {
/* shunt out overflow bits
*/
- while (xm >> (SP_MBITS + 1 + 3)) {
+ while (xm >> (SP_FBITS + 1 + 3)) {
SPXSRSX1();
}
} else {
/* normalize in grs extended single precision */
- while ((xm >> (SP_MBITS + 3)) == 0) {
+ while ((xm >> (SP_FBITS + 3)) == 0) {
xm <<= 1;
xe--;
}
}
- SPNORMRET1(xs, xe, xm, "sp_flong", x);
-}
-
-
-ieee754sp ieee754sp_fulong(u64 u)
-{
- if ((s64) u < 0)
- return ieee754sp_add(ieee754sp_1e63(),
- ieee754sp_flong(u & ~(1ULL << 63)));
- return ieee754sp_flong(u);
+ return ieee754sp_format(xs, xe, xm);
}
diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c
deleted file mode 100644
index 5bc993c3004..00000000000
--- a/arch/mips/math-emu/sp_frexp.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* IEEE754 floating point arithmetic
- * single precision
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754sp.h"
-
-/* close to ieeep754sp_logb
-*/
-ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
-{
- COMPXSP;
- CLEARCX;
- EXPLODEXSP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- case IEEE754_CLASS_QNAN:
- case IEEE754_CLASS_INF:
- case IEEE754_CLASS_ZERO:
- *eptr = 0;
- return x;
- case IEEE754_CLASS_DNORM:
- SPDNORMX;
- break;
- case IEEE754_CLASS_NORM:
- break;
- }
- *eptr = xe + 1;
- return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
-}
diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c
deleted file mode 100644
index 9c14e0c75bd..00000000000
--- a/arch/mips/math-emu/sp_logb.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* IEEE754 floating point arithmetic
- * single precision
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754sp.h"
-
-ieee754sp ieee754sp_logb(ieee754sp x)
-{
- COMPXSP;
-
- CLEARCX;
-
- EXPLODEXSP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- return ieee754sp_nanxcpt(x, "logb", x);
- case IEEE754_CLASS_QNAN:
- return x;
- case IEEE754_CLASS_INF:
- return ieee754sp_inf(0);
- case IEEE754_CLASS_ZERO:
- return ieee754sp_inf(1);
- case IEEE754_CLASS_DNORM:
- SPDNORMX;
- break;
- case IEEE754_CLASS_NORM:
- break;
- }
- return ieee754sp_fint(xe);
-}
diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c
deleted file mode 100644
index 25a0fbaa055..00000000000
--- a/arch/mips/math-emu/sp_modf.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* IEEE754 floating point arithmetic
- * single precision
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754sp.h"
-
-/* modf function is always exact for a finite number
-*/
-ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp *ip)
-{
- COMPXSP;
-
- CLEARCX;
-
- EXPLODEXSP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- case IEEE754_CLASS_QNAN:
- case IEEE754_CLASS_INF:
- case IEEE754_CLASS_ZERO:
- *ip = x;
- return x;
- case IEEE754_CLASS_DNORM:
- /* far to small */
- *ip = ieee754sp_zero(xs);
- return x;
- case IEEE754_CLASS_NORM:
- break;
- }
- if (xe < 0) {
- *ip = ieee754sp_zero(xs);
- return x;
- }
- if (xe >= SP_MBITS) {
- *ip = x;
- return ieee754sp_zero(xs);
- }
- /* generate ipart mantissa by clearing bottom bits
- */
- *ip = buildsp(xs, xe + SP_EBIAS,
- ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
- ~SP_HIDDEN_BIT);
-
- /* generate fpart mantissa by clearing top bits
- * and normalizing (must be able to normalize)
- */
- xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
- if (xm == 0)
- return ieee754sp_zero(xs);
-
- while ((xm >> SP_MBITS) == 0) {
- xm <<= 1;
- xe--;
- }
- return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
-}
diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c
index fa4675cf2aa..890c13a2965 100644
--- a/arch/mips/math-emu/sp_mul.c
+++ b/arch/mips/math-emu/sp_mul.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,23 +16,32 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_mul(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;
+
COMPXSP;
COMPYSP;
EXPLODEXSP;
EXPLODEYSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
FLUSHYSP;
@@ -51,8 +58,8 @@ ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -68,12 +75,13 @@ ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
return x;
- /* Infinity handling */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
@@ -108,63 +116,50 @@ ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
assert(xm & SP_HIDDEN_BIT);
assert(ym & SP_HIDDEN_BIT);
- {
- int re = xe + ye;
- int rs = xs ^ ys;
- unsigned rm;
-
- /* shunt to top of word */
- xm <<= 32 - (SP_MBITS + 1);
- ym <<= 32 - (SP_MBITS + 1);
-
- /* multiply 32bits xm,ym to give high 32bits rm with stickness
- */
- {
- unsigned short lxm = xm & 0xffff;
- unsigned short hxm = xm >> 16;
- unsigned short lym = ym & 0xffff;
- unsigned short hym = ym >> 16;
- unsigned lrm;
- unsigned hrm;
-
- lrm = lxm * lym; /* 16 * 16 => 32 */
- hrm = hxm * hym; /* 16 * 16 => 32 */
-
- {
- unsigned t = lxm * hym; /* 16 * 16 => 32 */
- {
- unsigned at = lrm + (t << 16);
- hrm += at < lrm;
- lrm = at;
- }
- hrm = hrm + (t >> 16);
- }
-
- {
- unsigned t = hxm * lym; /* 16 * 16 => 32 */
- {
- unsigned 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_MBITS + 1 + 3))) |
- ((rm << (SP_MBITS + 1 + 3)) != 0);
- re++;
- } else {
- rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
- ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
- }
- assert(rm & (SP_HIDDEN_BIT << 3));
-
- SPNORMRET2(rs, re, rm, "mul", x, y);
+ 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));
+
+ return ieee754sp_format(rs, re, rm);
}
diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c
deleted file mode 100644
index dd76196984c..00000000000
--- a/arch/mips/math-emu/sp_scalb.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* IEEE754 floating point arithmetic
- * single precision
- */
-/*
- * MIPS floating point support
- * Copyright (C) 1994-2000 Algorithmics Ltd.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- */
-
-
-#include "ieee754sp.h"
-
-ieee754sp ieee754sp_scalb(ieee754sp x, int n)
-{
- COMPXSP;
-
- CLEARCX;
-
- EXPLODEXSP;
-
- switch (xc) {
- case IEEE754_CLASS_SNAN:
- return ieee754sp_nanxcpt(x, "scalb", x, n);
- case IEEE754_CLASS_QNAN:
- case IEEE754_CLASS_INF:
- case IEEE754_CLASS_ZERO:
- return x;
- case IEEE754_CLASS_DNORM:
- SPDNORMX;
- break;
- case IEEE754_CLASS_NORM:
- break;
- }
- SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
-}
-
-
-ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
-{
- return ieee754sp_scalb(x, n);
-}
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
index ae4fcfafd85..f1ffaa9a17e 100644
--- a/arch/mips/math-emu/sp_simple.c
+++ b/arch/mips/math-emu/sp_simple.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,33 +16,17 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-int ieee754sp_finite(ieee754sp x)
-{
- return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
-}
-
-ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
-{
- CLEARCX;
- SPSIGN(x) = SPSIGN(y);
- return x;
-}
-
-
-ieee754sp ieee754sp_neg(ieee754sp x)
+union ieee754sp ieee754sp_neg(union ieee754sp x)
{
COMPXSP;
EXPLODEXSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
/*
@@ -55,30 +37,29 @@ ieee754sp ieee754sp_neg(ieee754sp x)
SPSIGN(x) ^= 1;
if (xc == IEEE754_CLASS_SNAN) {
- ieee754sp y = ieee754sp_indef();
- SETCX(IEEE754_INVALID_OPERATION);
+ union ieee754sp y = ieee754sp_indef();
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
SPSIGN(y) = SPSIGN(x);
- return ieee754sp_nanxcpt(y, "neg");
+ return ieee754sp_nanxcpt(y);
}
return x;
}
-
-ieee754sp ieee754sp_abs(ieee754sp x)
+union ieee754sp ieee754sp_abs(union ieee754sp x)
{
COMPXSP;
EXPLODEXSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
/* Clear sign ALWAYS, irrespective of NaN */
SPSIGN(x) = 0;
if (xc == IEEE754_CLASS_SNAN) {
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
}
return x;
diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c
index fed20175f5f..b7c098a86f9 100644
--- a/arch/mips/math-emu/sp_sqrt.c
+++ b/arch/mips/math-emu/sp_sqrt.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,15 +16,12 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-ieee754sp ieee754sp_sqrt(ieee754sp x)
+union ieee754sp ieee754sp_sqrt(union ieee754sp x)
{
int ix, s, q, m, t, i;
unsigned int r;
@@ -35,34 +30,38 @@ ieee754sp ieee754sp_sqrt(ieee754sp x)
/* take care of Inf and NaN */
EXPLODEXSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
/* x == INF or NAN? */
switch (xc) {
case IEEE754_CLASS_QNAN:
/* sqrt(Nan) = Nan */
- return ieee754sp_nanxcpt(x, "sqrt");
+ return ieee754sp_nanxcpt(x);
+
case IEEE754_CLASS_SNAN:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
+
case IEEE754_CLASS_ZERO:
/* sqrt(0) = 0 */
return x;
+
case IEEE754_CLASS_INF:
if (xs) {
/* sqrt(-Inf) = Nan */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
}
/* sqrt(+Inf) = Inf */
return x;
+
case IEEE754_CLASS_DNORM:
case IEEE754_CLASS_NORM:
if (xs) {
/* sqrt(-x) = Nan */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
}
break;
}
@@ -99,12 +98,12 @@ ieee754sp ieee754sp_sqrt(ieee754sp x)
}
if (ix != 0) {
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_INEXACT);
switch (ieee754_csr.rm) {
- case IEEE754_RP:
+ case FPU_CSR_RU:
q += 2;
break;
- case IEEE754_RN:
+ case FPU_CSR_RN:
q += (q & 1);
break;
}
diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c
index e595c6f3d0b..8592e49032b 100644
--- a/arch/mips/math-emu/sp_sub.c
+++ b/arch/mips/math-emu/sp_sub.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,23 +16,22 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
-ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
{
+ int s;
+
COMPXSP;
COMPYSP;
EXPLODEXSP;
EXPLODEYSP;
- CLEARCX;
+ ieee754_clearcx();
FLUSHXSP;
FLUSHYSP;
@@ -51,8 +48,8 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef());
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
@@ -68,14 +65,14 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
return x;
- /* Infinity handling
- */
-
+ /*
+ * Infinity handling
+ */
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
if (xs != ys)
return x;
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
@@ -87,15 +84,14 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
return x;
- /* Zero handling
- */
-
+ /*
+ * Zero handling
+ */
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs != ys)
return x;
else
- return ieee754sp_zero(ieee754_csr.rm ==
- IEEE754_RD);
+ return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
@@ -104,7 +100,7 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
/* quick fix up */
- DPSIGN(y) ^= 1;
+ SPSIGN(y) ^= 1;
return y;
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
@@ -133,14 +129,16 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
ym <<= 3;
if (xe > ye) {
- /* have to shift y fraction right to align
+ /*
+ * have to shift y fraction right to align
*/
- int s = xe - ye;
+ s = xe - ye;
SPXSRSYn(s);
} else if (ye > xe) {
- /* have to shift x fraction right to align
+ /*
+ * have to shift x fraction right to align
*/
- int s = ye - xe;
+ s = ye - xe;
SPXSRSXn(s);
}
assert(xe == ye);
@@ -153,7 +151,7 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
xe = xe;
xs = xs;
- if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+ if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */
SPXSRSX1(); /* shift preserving sticky */
}
} else {
@@ -167,17 +165,18 @@ ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
xs = ys;
}
if (xm == 0) {
- if (ieee754_csr.rm == IEEE754_RD)
+ if (ieee754_csr.rm == FPU_CSR_RD)
return ieee754sp_zero(1); /* round negative inf. => sign = -1 */
else
return ieee754sp_zero(0); /* other round modes => sign = 1 */
}
/* normalize to rounding precision
*/
- while ((xm >> (SP_MBITS + 3)) == 0) {
+ while ((xm >> (SP_FBITS + 3)) == 0) {
xm <<= 1;
xe--;
}
}
- SPNORMRET2(xs, xe, xm, "sub", x, y);
+
+ return ieee754sp_format(xs, xe, xm);
}
diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c
index 0fe9acc7716..091299a3179 100644
--- a/arch/mips/math-emu/sp_tint.c
+++ b/arch/mips/math-emu/sp_tint.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,20 +16,21 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
-#include <linux/kernel.h>
#include "ieee754sp.h"
-int ieee754sp_tint(ieee754sp x)
+int ieee754sp_tint(union ieee754sp x)
{
+ u32 residue;
+ int round;
+ int sticky;
+ int odd;
+
COMPXSP;
- CLEARCX;
+ ieee754_clearcx();
EXPLODEXSP;
FLUSHXSP;
@@ -40,10 +39,12 @@ int ieee754sp_tint(ieee754sp x)
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754si_indef();
+
case IEEE754_CLASS_ZERO:
return 0;
+
case IEEE754_CLASS_DNORM:
case IEEE754_CLASS_NORM:
break;
@@ -54,18 +55,13 @@ int ieee754sp_tint(ieee754sp x)
return -0x80000000;
/* Set invalid. We will only use overflow for floating
point overflow */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754si_indef();
}
/* oh gawd */
- if (xe > SP_MBITS) {
- xm <<= xe - SP_MBITS;
+ if (xe > SP_FBITS) {
+ xm <<= xe - SP_FBITS;
} else {
- u32 residue;
- int round;
- int sticky;
- int odd;
-
if (xe < -1) {
residue = xm;
round = 0;
@@ -76,51 +72,38 @@ int ieee754sp_tint(ieee754sp x)
* so we do it in two steps. Be aware that xe
* may be -1 */
residue = xm << (xe + 1);
- residue <<= 31 - SP_MBITS;
+ residue <<= 31 - SP_FBITS;
round = (residue >> 31) != 0;
sticky = (residue << 1) != 0;
- xm >>= SP_MBITS - xe;
+ xm >>= SP_FBITS - xe;
}
odd = (xm & 0x1) != 0x0;
switch (ieee754_csr.rm) {
- case IEEE754_RN:
+ case FPU_CSR_RN:
if (round && (sticky || odd))
xm++;
break;
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
break;
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if ((round || sticky) && !xs)
xm++;
break;
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if ((round || sticky) && xs)
xm++;
break;
}
if ((xm >> 31) != 0) {
/* This can happen after rounding */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754si_indef();
}
if (round || sticky)
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_INEXACT);
}
if (xs)
return -xm;
else
return xm;
}
-
-
-unsigned int ieee754sp_tuns(ieee754sp x)
-{
- ieee754sp hb = ieee754sp_1e31();
-
- /* what if x < 0 ?? */
- if (ieee754sp_lt(x, hb))
- return (unsigned) ieee754sp_tint(x);
-
- return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) |
- ((unsigned) 1 << 31);
-}
diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c
index d0ca6e22be2..9f3c742c1ce 100644
--- a/arch/mips/math-emu/sp_tlong.c
+++ b/arch/mips/math-emu/sp_tlong.c
@@ -5,8 +5,6 @@
* MIPS floating point support
* Copyright (C) 1994-2000 Algorithmics Ltd.
*
- * ########################################################################
- *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -18,19 +16,22 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#include "ieee754sp.h"
+#include "ieee754dp.h"
-s64 ieee754sp_tlong(ieee754sp x)
+s64 ieee754sp_tlong(union ieee754sp x)
{
+ u32 residue;
+ int round;
+ int sticky;
+ int odd;
+
COMPXDP; /* <-- need 64-bit mantissa tmp */
- CLEARCX;
+ ieee754_clearcx();
EXPLODEXSP;
FLUSHXSP;
@@ -39,10 +40,12 @@ s64 ieee754sp_tlong(ieee754sp x)
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754di_indef();
+
case IEEE754_CLASS_ZERO:
return 0;
+
case IEEE754_CLASS_DNORM:
case IEEE754_CLASS_NORM:
break;
@@ -53,69 +56,51 @@ s64 ieee754sp_tlong(ieee754sp x)
return -0x8000000000000000LL;
/* Set invalid. We will only use overflow for floating
point overflow */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754di_indef();
}
/* oh gawd */
- if (xe > SP_MBITS) {
- xm <<= xe - SP_MBITS;
- } else if (xe < SP_MBITS) {
- u32 residue;
- int round;
- int sticky;
- int odd;
-
+ if (xe > SP_FBITS) {
+ xm <<= xe - SP_FBITS;
+ } else if (xe < SP_FBITS) {
if (xe < -1) {
residue = xm;
round = 0;
sticky = residue != 0;
xm = 0;
} else {
- residue = xm << (32 - SP_MBITS + xe);
+ residue = xm << (32 - SP_FBITS + xe);
round = (residue >> 31) != 0;
sticky = (residue << 1) != 0;
- xm >>= SP_MBITS - xe;
+ xm >>= SP_FBITS - xe;
}
odd = (xm & 0x1) != 0x0;
switch (ieee754_csr.rm) {
- case IEEE754_RN:
+ case FPU_CSR_RN:
if (round && (sticky || odd))
xm++;
break;
- case IEEE754_RZ:
+ case FPU_CSR_RZ:
break;
- case IEEE754_RU: /* toward +Infinity */
+ case FPU_CSR_RU: /* toward +Infinity */
if ((round || sticky) && !xs)
xm++;
break;
- case IEEE754_RD: /* toward -Infinity */
+ case FPU_CSR_RD: /* toward -Infinity */
if ((round || sticky) && xs)
xm++;
break;
}
if ((xm >> 63) != 0) {
/* This can happen after rounding */
- SETCX(IEEE754_INVALID_OPERATION);
- return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754di_indef();
}
if (round || sticky)
- SETCX(IEEE754_INEXACT);
+ ieee754_setcx(IEEE754_INEXACT);
}
if (xs)
return -xm;
else
return xm;
}
-
-
-u64 ieee754sp_tulong(ieee754sp x)
-{
- ieee754sp hb = ieee754sp_1e63();
-
- /* what if x < 0 ?? */
- if (ieee754sp_lt(x, hb))
- return (u64) ieee754sp_tlong(x);
-
- return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
- (1ULL << 63);
-}
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index 729e7702b1d..05b1d7cf951 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -6,7 +6,6 @@
* Copyright (C) 2005-2007 Cavium Networks
*/
#include <linux/export.h>
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
@@ -19,6 +18,7 @@
#include <asm/bootinfo.h>
#include <asm/cacheops.h>
#include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/r4kcache.h>
@@ -137,8 +137,10 @@ static void octeon_flush_cache_sigtramp(unsigned long addr)
{
struct vm_area_struct *vma;
+ down_read(&current->mm->mmap_sem);
vma = find_vma(current->mm, addr);
octeon_flush_icache_all_cores(vma);
+ up_read(&current->mm->mmap_sem);
}
@@ -186,9 +188,10 @@ static void probe_octeon(void)
unsigned long dcache_size;
unsigned int config1;
struct cpuinfo_mips *c = &current_cpu_data;
+ int cputype = current_cpu_type();
config1 = read_c0_config1();
- switch (c->cputype) {
+ switch (cputype) {
case CPU_CAVIUM_OCTEON:
case CPU_CAVIUM_OCTEON_PLUS:
c->icache.linesz = 2 << ((config1 >> 19) & 7);
@@ -199,7 +202,7 @@ static void probe_octeon(void)
c->icache.sets * c->icache.ways * c->icache.linesz;
c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
c->dcache.linesz = 128;
- if (c->cputype == CPU_CAVIUM_OCTEON_PLUS)
+ if (cputype == CPU_CAVIUM_OCTEON_PLUS)
c->dcache.sets = 2; /* CN5XXX has two Dcache sets */
else
c->dcache.sets = 1; /* CN3XXX has one Dcache set */
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 2fcde0c8ea0..135ec313c1f 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -9,7 +9,6 @@
* Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
* Copyright (C) 2001, 2004, 2007 Maciej W. Rozycki
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index f749f687ee8..f2e8302fa70 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -7,11 +7,13 @@
* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
+#include <linux/cpu_pm.h>
#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
+#include <linux/preempt.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/mm.h>
@@ -24,6 +26,7 @@
#include <asm/cacheops.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -48,14 +51,14 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
{
preempt_disable();
-#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
+#ifndef CONFIG_MIPS_MT_SMP
smp_call_function(func, info, 1);
#endif
func(info);
preempt_enable();
}
-#if defined(CONFIG_MIPS_CMP)
+#if defined(CONFIG_MIPS_CMP) || defined(CONFIG_MIPS_CPS)
#define cpu_has_safe_index_cacheops 0
#else
#define cpu_has_safe_index_cacheops 1
@@ -103,24 +106,61 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
static inline void r4k_blast_dcache_page_dc64(unsigned long addr)
{
- R4600_HIT_CACHEOP_WAR_IMPL;
blast_dcache64_page(addr);
}
+static inline void r4k_blast_dcache_page_dc128(unsigned long addr)
+{
+ blast_dcache128_page(addr);
+}
+
static void r4k_blast_dcache_page_setup(void)
{
unsigned long dc_lsize = cpu_dcache_line_size();
- if (dc_lsize == 0)
+ switch (dc_lsize) {
+ case 0:
r4k_blast_dcache_page = (void *)cache_noop;
- else if (dc_lsize == 16)
+ break;
+ case 16:
r4k_blast_dcache_page = blast_dcache16_page;
- else if (dc_lsize == 32)
+ break;
+ case 32:
r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
- else if (dc_lsize == 64)
+ break;
+ case 64:
r4k_blast_dcache_page = r4k_blast_dcache_page_dc64;
+ break;
+ case 128:
+ r4k_blast_dcache_page = r4k_blast_dcache_page_dc128;
+ break;
+ default:
+ break;
+ }
+}
+
+#ifndef CONFIG_EVA
+#define r4k_blast_dcache_user_page r4k_blast_dcache_page
+#else
+
+static void (*r4k_blast_dcache_user_page)(unsigned long addr);
+
+static void r4k_blast_dcache_user_page_setup(void)
+{
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
+ if (dc_lsize == 0)
+ r4k_blast_dcache_user_page = (void *)cache_noop;
+ else if (dc_lsize == 16)
+ r4k_blast_dcache_user_page = blast_dcache16_user_page;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache_user_page = blast_dcache32_user_page;
+ else if (dc_lsize == 64)
+ r4k_blast_dcache_user_page = blast_dcache64_user_page;
}
+#endif
+
static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
static void r4k_blast_dcache_page_indexed_setup(void)
@@ -135,6 +175,8 @@ static void r4k_blast_dcache_page_indexed_setup(void)
r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
else if (dc_lsize == 64)
r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed;
+ else if (dc_lsize == 128)
+ r4k_blast_dcache_page_indexed = blast_dcache128_page_indexed;
}
void (* r4k_blast_dcache)(void);
@@ -152,6 +194,8 @@ static void r4k_blast_dcache_setup(void)
r4k_blast_dcache = blast_dcache32;
else if (dc_lsize == 64)
r4k_blast_dcache = blast_dcache64;
+ else if (dc_lsize == 128)
+ r4k_blast_dcache = blast_dcache128;
}
/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
@@ -235,12 +279,37 @@ static void r4k_blast_icache_page_setup(void)
r4k_blast_icache_page = (void *)cache_noop;
else if (ic_lsize == 16)
r4k_blast_icache_page = blast_icache16_page;
+ else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2)
+ r4k_blast_icache_page = loongson2_blast_icache32_page;
else if (ic_lsize == 32)
r4k_blast_icache_page = blast_icache32_page;
else if (ic_lsize == 64)
r4k_blast_icache_page = blast_icache64_page;
+ else if (ic_lsize == 128)
+ r4k_blast_icache_page = blast_icache128_page;
}
+#ifndef CONFIG_EVA
+#define r4k_blast_icache_user_page r4k_blast_icache_page
+#else
+
+static void (*r4k_blast_icache_user_page)(unsigned long addr);
+
+static void __cpuinit r4k_blast_icache_user_page_setup(void)
+{
+ unsigned long ic_lsize = cpu_icache_line_size();
+
+ if (ic_lsize == 0)
+ r4k_blast_icache_user_page = (void *)cache_noop;
+ else if (ic_lsize == 16)
+ r4k_blast_icache_user_page = blast_icache16_user_page;
+ else if (ic_lsize == 32)
+ r4k_blast_icache_user_page = blast_icache32_user_page;
+ else if (ic_lsize == 64)
+ r4k_blast_icache_user_page = blast_icache64_user_page;
+}
+
+#endif
static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
@@ -259,6 +328,9 @@ static void r4k_blast_icache_page_indexed_setup(void)
else if (TX49XX_ICACHE_INDEX_INV_WAR)
r4k_blast_icache_page_indexed =
tx49_blast_icache32_page_indexed;
+ else if (current_cpu_type() == CPU_LOONGSON2)
+ r4k_blast_icache_page_indexed =
+ loongson2_blast_icache32_page_indexed;
else
r4k_blast_icache_page_indexed =
blast_icache32_page_indexed;
@@ -282,10 +354,14 @@ static void r4k_blast_icache_setup(void)
r4k_blast_icache = blast_r4600_v1_icache32;
else if (TX49XX_ICACHE_INDEX_INV_WAR)
r4k_blast_icache = tx49_blast_icache32;
+ else if (current_cpu_type() == CPU_LOONGSON2)
+ r4k_blast_icache = loongson2_blast_icache32;
else
r4k_blast_icache = blast_icache32;
} else if (ic_lsize == 64)
r4k_blast_icache = blast_icache64;
+ else if (ic_lsize == 128)
+ r4k_blast_icache = blast_icache128;
}
static void (* r4k_blast_scache_page)(unsigned long addr);
@@ -344,14 +420,9 @@ static void r4k_blast_scache_setup(void)
static inline void local_r4k___flush_cache_all(void * args)
{
-#if defined(CONFIG_CPU_LOONGSON2)
- r4k_blast_scache();
- return;
-#endif
- r4k_blast_dcache();
- r4k_blast_icache();
-
switch (current_cpu_type()) {
+ case CPU_LOONGSON2:
+ case CPU_LOONGSON3:
case CPU_R4000SC:
case CPU_R4000MC:
case CPU_R4400SC:
@@ -359,7 +430,18 @@ static inline void local_r4k___flush_cache_all(void * args)
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
+ /*
+ * These caches are inclusive caches, that is, if something
+ * is not cached in the S-cache, we know it also won't be
+ * in one of the primary caches.
+ */
r4k_blast_scache();
+ break;
+
+ default:
+ r4k_blast_dcache();
+ r4k_blast_icache();
+ break;
}
}
@@ -370,7 +452,7 @@ static void r4k___flush_cache_all(void)
static inline int has_valid_asid(const struct mm_struct *mm)
{
-#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
+#ifdef CONFIG_MIPS_MT_SMP
int i;
for_each_online_cpu(i)
@@ -505,7 +587,8 @@ static inline void local_r4k_flush_cache_page(void *args)
}
if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
- r4k_blast_dcache_page(addr);
+ vaddr ? r4k_blast_dcache_page(addr) :
+ r4k_blast_dcache_user_page(addr);
if (exec && !cpu_icache_snoops_remote_store)
r4k_blast_scache_page(addr);
}
@@ -516,7 +599,8 @@ static inline void local_r4k_flush_cache_page(void *args)
if (cpu_context(cpu, mm) != 0)
drop_mmu_context(mm, cpu);
} else
- r4k_blast_icache_page(addr);
+ vaddr ? r4k_blast_icache_page(addr) :
+ r4k_blast_icache_user_page(addr);
}
if (vaddr) {
@@ -570,8 +654,28 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo
if (end - start > icache_size)
r4k_blast_icache();
- else
- protected_blast_icache_range(start, end);
+ else {
+ switch (boot_cpu_type()) {
+ case CPU_LOONGSON2:
+ protected_loongson2_blast_icache_range(start, end);
+ break;
+
+ default:
+ protected_blast_icache_range(start, end);
+ break;
+ }
+ }
+#ifdef CONFIG_EVA
+ /*
+ * Due to all possible segment mappings, there might cache aliases
+ * caused by the bootloader being in non-EVA mode, and the CPU switching
+ * to EVA during early kernel init. It's best to flush the scache
+ * to avoid having secondary cores fetching stale data and lead to
+ * kernel crashes.
+ */
+ bc_wback_inv(start, (end - start));
+ __sync();
+#endif
}
static inline void local_r4k_flush_icache_range_ipi(void *args)
@@ -594,18 +698,20 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
instruction_hazard();
}
-#ifdef CONFIG_DMA_NONCOHERENT
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
/* Catch bad driver code */
BUG_ON(size == 0);
+ preempt_disable();
if (cpu_has_inclusive_pcaches) {
if (size >= scache_size)
r4k_blast_scache();
else
blast_scache_range(addr, addr + size);
+ preempt_enable();
__sync();
return;
}
@@ -621,6 +727,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
R4600_HIT_CACHEOP_WAR_IMPL;
blast_dcache_range(addr, addr + size);
}
+ preempt_enable();
bc_wback_inv(addr, size);
__sync();
@@ -631,6 +738,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
/* Catch bad driver code */
BUG_ON(size == 0);
+ preempt_disable();
if (cpu_has_inclusive_pcaches) {
if (size >= scache_size)
r4k_blast_scache();
@@ -645,6 +753,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
*/
blast_inv_scache_range(addr, addr + size);
}
+ preempt_enable();
__sync();
return;
}
@@ -655,11 +764,12 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
R4600_HIT_CACHEOP_WAR_IMPL;
blast_inv_dcache_range(addr, addr + size);
}
+ preempt_enable();
bc_inv(addr, size);
__sync();
}
-#endif /* CONFIG_DMA_NONCOHERENT */
+#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
/*
* While we're protected against bad userland addresses we don't care
@@ -780,20 +890,30 @@ static inline void rm7k_erratum31(void)
static inline void alias_74k_erratum(struct cpuinfo_mips *c)
{
+ unsigned int imp = c->processor_id & PRID_IMP_MASK;
+ unsigned int rev = c->processor_id & PRID_REV_MASK;
+
/*
* Early versions of the 74K do not update the cache tags on a
* vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG
* aliases. In this case it is better to treat the cache as always
* having aliases.
*/
- if ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(2, 4, 0))
- c->dcache.flags |= MIPS_CACHE_VTAG;
- if ((c->processor_id & 0xff) == PRID_REV_ENCODE_332(2, 4, 0))
- write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
- if (((c->processor_id & 0xff00) == PRID_IMP_1074K) &&
- ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(1, 1, 0))) {
- c->dcache.flags |= MIPS_CACHE_VTAG;
- write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
+ switch (imp) {
+ case PRID_IMP_74K:
+ if (rev <= PRID_REV_ENCODE_332(2, 4, 0))
+ c->dcache.flags |= MIPS_CACHE_VTAG;
+ if (rev == PRID_REV_ENCODE_332(2, 4, 0))
+ write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
+ break;
+ case PRID_IMP_1074K:
+ if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) {
+ c->dcache.flags |= MIPS_CACHE_VTAG;
+ write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
+ }
+ break;
+ default:
+ BUG();
}
}
@@ -809,7 +929,7 @@ static void probe_pcache(void)
unsigned long config1;
unsigned int lsize;
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_R4600: /* QED style two way caches? */
case CPU_R4700:
case CPU_R5000:
@@ -971,6 +1091,48 @@ static void probe_pcache(void)
c->dcache.waybit = 0;
break;
+ case CPU_LOONGSON3:
+ config1 = read_c0_config1();
+ lsize = (config1 >> 19) & 7;
+ if (lsize)
+ c->icache.linesz = 2 << lsize;
+ else
+ c->icache.linesz = 0;
+ c->icache.sets = 64 << ((config1 >> 22) & 7);
+ c->icache.ways = 1 + ((config1 >> 16) & 7);
+ icache_size = c->icache.sets *
+ c->icache.ways *
+ c->icache.linesz;
+ c->icache.waybit = 0;
+
+ lsize = (config1 >> 10) & 7;
+ if (lsize)
+ c->dcache.linesz = 2 << lsize;
+ else
+ c->dcache.linesz = 0;
+ c->dcache.sets = 64 << ((config1 >> 13) & 7);
+ c->dcache.ways = 1 + ((config1 >> 7) & 7);
+ dcache_size = c->dcache.sets *
+ c->dcache.ways *
+ c->dcache.linesz;
+ c->dcache.waybit = 0;
+ break;
+
+ case CPU_CAVIUM_OCTEON3:
+ /* For now lie about the number of ways. */
+ c->icache.linesz = 128;
+ c->icache.sets = 16;
+ c->icache.ways = 8;
+ c->icache.flags |= MIPS_CACHE_VTAG;
+ icache_size = c->icache.sets * c->icache.ways * c->icache.linesz;
+
+ c->dcache.linesz = 128;
+ c->dcache.ways = 8;
+ c->dcache.sets = 8;
+ dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz;
+ c->options |= MIPS_CPU_PREFETCH;
+ break;
+
default:
if (!(config & MIPS_CONF_M))
panic("Don't know how to probe P-caches on this cpu.");
@@ -981,10 +1143,14 @@ static void probe_pcache(void)
*/
config1 = read_c0_config1();
- if ((lsize = ((config1 >> 19) & 7)))
- c->icache.linesz = 2 << lsize;
- else
- c->icache.linesz = lsize;
+ lsize = (config1 >> 19) & 7;
+
+ /* IL == 7 is reserved */
+ if (lsize == 7)
+ panic("Invalid icache line size");
+
+ c->icache.linesz = lsize ? 2 << lsize : 0;
+
c->icache.sets = 32 << (((config1 >> 22) + 1) & 7);
c->icache.ways = 1 + ((config1 >> 16) & 7);
@@ -1001,10 +1167,14 @@ static void probe_pcache(void)
*/
c->dcache.flags = 0;
- if ((lsize = ((config1 >> 10) & 7)))
- c->dcache.linesz = 2 << lsize;
- else
- c->dcache.linesz= lsize;
+ lsize = (config1 >> 10) & 7;
+
+ /* DL == 7 is reserved */
+ if (lsize == 7)
+ panic("Invalid dcache line size");
+
+ c->dcache.linesz = lsize ? 2 << lsize : 0;
+
c->dcache.sets = 32 << (((config1 >> 13) + 1) & 7);
c->dcache.ways = 1 + ((config1 >> 7) & 7);
@@ -1025,7 +1195,8 @@ static void probe_pcache(void)
* presumably no vendor is shipping his hardware in the "bad"
* configuration.
*/
- if ((prid & 0xff00) == PRID_IMP_R4000 && (prid & 0xff) < 0x40 &&
+ if ((prid & PRID_IMP_MASK) == PRID_IMP_R4000 &&
+ (prid & PRID_REV_MASK) < PRID_REV_R4400 &&
!(config & CONF_SC) && c->icache.linesz != 16 &&
PAGE_SIZE <= 0x8000)
panic("Improper R4000SC processor configuration detected");
@@ -1045,7 +1216,7 @@ static void probe_pcache(void)
* normally they'd suffer from aliases but magic in the hardware deals
* with that for us so we don't need to take care ourselves.
*/
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_20KC:
case CPU_25KF:
case CPU_SB1:
@@ -1065,11 +1236,21 @@ static void probe_pcache(void)
case CPU_34K:
case CPU_74K:
case CPU_1004K:
- if (c->cputype == CPU_74K)
+ case CPU_1074K:
+ case CPU_INTERAPTIV:
+ case CPU_P5600:
+ case CPU_PROAPTIV:
+ case CPU_M5150:
+ if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K))
alias_74k_erratum(c);
- if ((read_c0_config7() & (1 << 16))) {
- /* effectively physically indexed dcache,
- thus no virtual aliases. */
+ if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
+ (c->icache.waysize > PAGE_SIZE))
+ c->icache.flags |= MIPS_CACHE_ALIASES;
+ if (read_c0_config7() & MIPS_CONF7_AR) {
+ /*
+ * Effectively physically indexed dcache,
+ * thus no virtual aliases.
+ */
c->dcache.flags |= MIPS_CACHE_PINDEX;
break;
}
@@ -1078,7 +1259,7 @@ static void probe_pcache(void)
c->dcache.flags |= MIPS_CACHE_ALIASES;
}
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_20KC:
/*
* Some older 20Kc chips doesn't have the 'VI' bit in
@@ -1090,15 +1271,14 @@ static void probe_pcache(void)
case CPU_ALCHEMY:
c->icache.flags |= MIPS_CACHE_IC_F_DC;
break;
- }
-#ifdef CONFIG_CPU_LOONGSON2
- /*
- * LOONGSON2 has 4 way icache, but when using indexed cache op,
- * one op will act on all 4 ways
- */
- c->icache.ways = 1;
-#endif
+ case CPU_LOONGSON2:
+ /*
+ * LOONGSON2 has 4 way icache, but when using indexed cache op,
+ * one op will act on all 4 ways
+ */
+ c->icache.ways = 1;
+ }
printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
icache_size >> 10,
@@ -1174,7 +1354,6 @@ static int probe_scache(void)
return 1;
}
-#if defined(CONFIG_CPU_LOONGSON2)
static void __init loongson2_sc_init(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -1190,7 +1369,33 @@ static void __init loongson2_sc_init(void)
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
}
-#endif
+
+static void __init loongson3_sc_init(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+ unsigned int config2, lsize;
+
+ config2 = read_c0_config2();
+ lsize = (config2 >> 4) & 15;
+ if (lsize)
+ c->scache.linesz = 2 << lsize;
+ else
+ c->scache.linesz = 0;
+ c->scache.sets = 64 << ((config2 >> 8) & 15);
+ c->scache.ways = 1 + (config2 & 15);
+
+ scache_size = c->scache.sets *
+ c->scache.ways *
+ c->scache.linesz;
+ /* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */
+ scache_size *= 4;
+ c->scache.waybit = 0;
+ pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+ if (scache_size)
+ c->options |= MIPS_CPU_INCLUSIVE_CACHES;
+ return;
+}
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
@@ -1207,7 +1412,7 @@ static void setup_scache(void)
* processors don't have a S-cache that would be relevant to the
* Linux memory management.
*/
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_R4000SC:
case CPU_R4000MC:
case CPU_R4400SC:
@@ -1240,11 +1445,15 @@ static void setup_scache(void)
#endif
return;
-#if defined(CONFIG_CPU_LOONGSON2)
case CPU_LOONGSON2:
loongson2_sc_init();
return;
-#endif
+
+ case CPU_LOONGSON3:
+ loongson3_sc_init();
+ return;
+
+ case CPU_CAVIUM_OCTEON3:
case CPU_XLP:
/* don't need to worry about L2, fully coherent */
return;
@@ -1384,9 +1593,8 @@ static void r4k_cache_error_setup(void)
{
extern char __weak except_vec2_generic;
extern char __weak except_vec2_sb1;
- struct cpuinfo_mips *c = &current_cpu_data;
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_SB1:
case CPU_SB1A:
set_uncached_handler(0x100, &except_vec2_sb1, 0x80);
@@ -1416,6 +1624,10 @@ void r4k_cache_init(void)
r4k_blast_scache_page_setup();
r4k_blast_scache_page_indexed_setup();
r4k_blast_scache_setup();
+#ifdef CONFIG_EVA
+ r4k_blast_dcache_user_page_setup();
+ r4k_blast_icache_user_page_setup();
+#endif
/*
* Some MIPS32 and MIPS64 processors have physically indexed caches.
@@ -1447,7 +1659,7 @@ void r4k_cache_init(void)
flush_icache_range = r4k_flush_icache_range;
local_flush_icache_range = local_r4k_flush_icache_range;
-#if defined(CONFIG_DMA_NONCOHERENT)
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
if (coherentio) {
_dma_cache_wback_inv = (void *)cache_noop;
_dma_cache_wback = (void *)cache_noop;
@@ -1472,3 +1684,26 @@ void r4k_cache_init(void)
coherency_setup();
board_cache_error_setup = r4k_cache_error_setup;
}
+
+static int r4k_cache_pm_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ coherency_setup();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block r4k_cache_pm_notifier_block = {
+ .notifier_call = r4k_cache_pm_notifier,
+};
+
+int __init r4k_cache_init_pm(void)
+{
+ return cpu_pm_register_notifier(&r4k_cache_pm_notifier_block);
+}
+arch_initcall(r4k_cache_init_pm);
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 15f813c303b..f7b91d3a371 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -8,7 +8,6 @@
*/
#include <linux/fs.h>
#include <linux/fcntl.h>
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
#include <linux/module.h>
@@ -30,15 +29,16 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
unsigned long pfn);
void (*flush_icache_range)(unsigned long start, unsigned long end);
+EXPORT_SYMBOL_GPL(flush_icache_range);
void (*local_flush_icache_range)(unsigned long start, unsigned long end);
+EXPORT_SYMBOL_GPL(local_flush_icache_range);
void (*__flush_cache_vmap)(void);
void (*__flush_cache_vunmap)(void);
void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
-void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
-
EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
+void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
/* MIPS specific cache operations */
void (*flush_cache_sigtramp)(unsigned long addr);
@@ -50,7 +50,7 @@ EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
EXPORT_SYMBOL(flush_data_cache_page);
EXPORT_SYMBOL(flush_icache_all);
-#ifdef CONFIG_DMA_NONCOHERENT
+#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
/* DMA cache operations. */
void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
@@ -59,7 +59,7 @@ void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
-#endif /* CONFIG_DMA_NONCOHERENT */
+#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
/*
* We could optimize the case where the cache argument is not BCACHE but
diff --git a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S
index 191cf6e0c72..5d5f29681a2 100644
--- a/arch/mips/mm/cex-sb1.S
+++ b/arch/mips/mm/cex-sb1.S
@@ -15,7 +15,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <linux/init.h>
#include <asm/asm.h>
#include <asm/regdef.h>
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 664e523653d..44b6dff5aba 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -18,10 +18,12 @@
#include <linux/highmem.h>
#include <asm/cache.h>
+#include <asm/cpu-type.h>
#include <asm/io.h>
#include <dma-coherence.h>
+#ifdef CONFIG_DMA_MAYBE_COHERENT
int coherentio = 0; /* User defined DMA coherency from command line. */
EXPORT_SYMBOL_GPL(coherentio);
int hw_coherentio = 0; /* Actual hardware supported DMA coherency setting. */
@@ -41,6 +43,7 @@ static int __init setnocoherentio(char *str)
return 0;
}
early_param("nocoherentio", setnocoherentio);
+#endif
static inline struct page *dma_addr_to_page(struct device *dev,
dma_addr_t dma_addr)
@@ -296,7 +299,6 @@ static void mips_dma_sync_single_for_cpu(struct device *dev,
static void mips_dma_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
{
- plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev))
__dma_sync(dma_addr_to_page(dev, dma_handle),
dma_handle & ~PAGE_MASK, size, direction);
@@ -307,12 +309,10 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev,
{
int i;
- /* Make sure that gcc doesn't leave the empty loop body. */
- for (i = 0; i < nelems; i++, sg++) {
- if (cpu_needs_post_dma_flush(dev))
+ if (cpu_needs_post_dma_flush(dev))
+ for (i = 0; i < nelems; i++, sg++)
__dma_sync(sg_page(sg), sg->offset, sg->length,
direction);
- }
}
static void mips_dma_sync_sg_for_device(struct device *dev,
@@ -320,17 +320,15 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
{
int i;
- /* Make sure that gcc doesn't leave the empty loop body. */
- for (i = 0; i < nelems; i++, sg++) {
- if (!plat_device_is_coherent(dev))
+ if (!plat_device_is_coherent(dev))
+ for (i = 0; i < nelems; i++, sg++)
__dma_sync(sg_page(sg), sg->offset, sg->length,
direction);
- }
}
int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
- return plat_dma_mapping_error(dev, dma_addr);
+ return 0;
}
int mips_dma_supported(struct device *dev, u64 mask)
@@ -343,7 +341,6 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
{
BUG_ON(direction == DMA_NONE);
- plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev))
__dma_sync_virtual(vaddr, size, direction);
}
diff --git a/arch/mips/mm/hugetlbpage.c b/arch/mips/mm/hugetlbpage.c
index 01fda4419ed..4ec8ee10d37 100644
--- a/arch/mips/mm/hugetlbpage.c
+++ b/arch/mips/mm/hugetlbpage.c
@@ -11,7 +11,6 @@
* Copyright (C) 2008, 2009 Cavium Networks, Inc.
*/
-#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
@@ -85,11 +84,6 @@ int pud_huge(pud_t pud)
return (pud_val(pud) & _PAGE_HUGE) != 0;
}
-int pmd_huge_support(void)
-{
- return 1;
-}
-
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index e205ef598e9..6e4413330e3 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -44,27 +44,6 @@
#include <asm/tlb.h>
#include <asm/fixmap.h>
-/* Atomicity and interruptability */
-#ifdef CONFIG_MIPS_MT_SMTC
-
-#include <asm/mipsmtregs.h>
-
-#define ENTER_CRITICAL(flags) \
- { \
- unsigned int mvpflags; \
- local_irq_save(flags);\
- mvpflags = dvpe()
-#define EXIT_CRITICAL(flags) \
- evpe(mvpflags); \
- local_irq_restore(flags); \
- }
-#else
-
-#define ENTER_CRITICAL(flags) local_irq_save(flags)
-#define EXIT_CRITICAL(flags) local_irq_restore(flags)
-
-#endif /* CONFIG_MIPS_MT_SMTC */
-
/*
* We have up to 8 empty zeroed pages so we can map one of the right colour
* when needed. This is necessary only on R4000 / R4400 SC and MC versions
@@ -100,21 +79,7 @@ void setup_zero_pages(void)
zero_page_mask = ((PAGE_SIZE << order) - 1) & PAGE_MASK;
}
-#ifdef CONFIG_MIPS_MT_SMTC
-static pte_t *kmap_coherent_pte;
-static void __init kmap_coherent_init(void)
-{
- unsigned long vaddr;
-
- /* cache the first coherent kmap pte */
- vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
- kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
-}
-#else
-static inline void kmap_coherent_init(void) {}
-#endif
-
-void *kmap_coherent(struct page *page, unsigned long addr)
+static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot)
{
enum fixed_addresses idx;
unsigned long vaddr, flags, entrylo;
@@ -124,62 +89,50 @@ void *kmap_coherent(struct page *page, unsigned long addr)
BUG_ON(Page_dcache_dirty(page));
- inc_preempt_count();
+ pagefault_disable();
idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
-#ifdef CONFIG_MIPS_MT_SMTC
- idx += FIX_N_COLOURS * smp_processor_id() +
- (in_interrupt() ? (FIX_N_COLOURS * NR_CPUS) : 0);
-#else
idx += in_interrupt() ? FIX_N_COLOURS : 0;
-#endif
vaddr = __fix_to_virt(FIX_CMAP_END - idx);
- pte = mk_pte(page, PAGE_KERNEL);
+ pte = mk_pte(page, prot);
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
entrylo = pte.pte_high;
#else
entrylo = pte_to_entrylo(pte_val(pte));
#endif
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
old_ctx = read_c0_entryhi();
write_c0_entryhi(vaddr & (PAGE_MASK << 1));
write_c0_entrylo0(entrylo);
write_c0_entrylo1(entrylo);
-#ifdef CONFIG_MIPS_MT_SMTC
- set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
- /* preload TLB instead of local_flush_tlb_one() */
- mtc0_tlbw_hazard();
- tlb_probe();
- tlb_probe_hazard();
- tlbidx = read_c0_index();
- mtc0_tlbw_hazard();
- if (tlbidx < 0)
- tlb_write_random();
- else
- tlb_write_indexed();
-#else
tlbidx = read_c0_wired();
write_c0_wired(tlbidx + 1);
write_c0_index(tlbidx);
mtc0_tlbw_hazard();
tlb_write_indexed();
-#endif
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
- EXIT_CRITICAL(flags);
+ local_irq_restore(flags);
return (void*) vaddr;
}
-#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
+void *kmap_coherent(struct page *page, unsigned long addr)
+{
+ return __kmap_pgprot(page, addr, PAGE_KERNEL);
+}
+
+void *kmap_noncoherent(struct page *page, unsigned long addr)
+{
+ return __kmap_pgprot(page, addr, PAGE_KERNEL_NC);
+}
void kunmap_coherent(void)
{
-#ifndef CONFIG_MIPS_MT_SMTC
unsigned int wired;
unsigned long flags, old_ctx;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
old_ctx = read_c0_entryhi();
wired = read_c0_wired() - 1;
write_c0_wired(wired);
@@ -191,10 +144,8 @@ void kunmap_coherent(void)
tlb_write_indexed();
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
- EXIT_CRITICAL(flags);
-#endif
- dec_preempt_count();
- preempt_check_resched();
+ local_irq_restore(flags);
+ pagefault_enable();
}
void copy_user_highpage(struct page *to, struct page *from,
@@ -259,7 +210,7 @@ EXPORT_SYMBOL_GPL(copy_from_user_page);
void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
-#if defined(CONFIG_HIGHMEM) || defined(CONFIG_MIPS_MT_SMTC)
+#ifdef CONFIG_HIGHMEM
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
@@ -330,8 +281,6 @@ void __init paging_init(void)
#ifdef CONFIG_HIGHMEM
kmap_init();
#endif
- kmap_coherent_init();
-
#ifdef CONFIG_ZONE_DMA
max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
#endif
@@ -425,10 +374,20 @@ void free_initrd_mem(unsigned long start, unsigned long end)
}
#endif
+void (*free_init_pages_eva)(void *begin, void *end) = NULL;
+
void __init_refok free_initmem(void)
{
prom_free_prom_memory();
- free_initmem_default(POISON_FREE_INITMEM);
+ /*
+ * Let the platform define a specific function to free the
+ * init section since EVA may have used any possible mapping
+ * between virtual and physical addresses.
+ */
+ if (free_init_pages_eva)
+ free_init_pages_eva((void *)&__init_begin, (void *)&__init_end);
+ else
+ free_initmem_default(POISON_FREE_INITMEM);
}
#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c
index 218c2109a55..b611102e23b 100644
--- a/arch/mips/mm/page.c
+++ b/arch/mips/mm/page.c
@@ -8,7 +8,6 @@
* Copyright (C) 2008 Thiemo Seufer
* Copyright (C) 2012 MIPS Technologies, Inc.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
@@ -18,6 +17,7 @@
#include <asm/bugs.h>
#include <asm/cacheops.h>
+#include <asm/cpu-type.h>
#include <asm/inst.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -273,7 +273,7 @@ void build_clear_page(void)
uasm_i_ori(&buf, A2, A0, off);
if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
- uasm_i_lui(&buf, AT, 0xa000);
+ uasm_i_lui(&buf, AT, uasm_rel_hi(0xa0000000));
off = cache_line_size ? min(8, pref_bias_clear_store / cache_line_size)
* cache_line_size : 0;
@@ -424,7 +424,7 @@ void build_copy_page(void)
uasm_i_ori(&buf, A2, A0, off);
if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
- uasm_i_lui(&buf, AT, 0xa000);
+ uasm_i_lui(&buf, AT, uasm_rel_hi(0xa0000000));
off = cache_line_size ? min(8, pref_bias_copy_load / cache_line_size) *
cache_line_size : 0;
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 5d01392e351..99eb8fabab6 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
+#include <asm/cpu-type.h>
#include <asm/mipsregs.h>
#include <asm/bcache.h>
#include <asm/cacheops.h>
@@ -71,10 +72,14 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
unsigned int tmp;
/* Check the bypass bit (L2B) */
- switch (c->cputype) {
+ switch (current_cpu_type()) {
case CPU_34K:
case CPU_74K:
case CPU_1004K:
+ case CPU_1074K:
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ case CPU_P5600:
case CPU_BMIPS5000:
if (config2 & (1 << 12))
return 0;
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index aaffbba3370..9ac1efcfbcc 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -6,7 +6,6 @@
#undef DEBUG
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/bitops.h>
diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
index 79bca3130bd..a5427c6e975 100644
--- a/arch/mips/mm/tlb-funcs.S
+++ b/arch/mips/mm/tlb-funcs.S
@@ -16,12 +16,12 @@
#define FASTPATH_SIZE 128
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+EXPORT(tlbmiss_handler_setup_pgd_start)
LEAF(tlbmiss_handler_setup_pgd)
- .space 16 * 4
+1: j 1b /* Dummy, will be replaced. */
+ .space 64
END(tlbmiss_handler_setup_pgd)
EXPORT(tlbmiss_handler_setup_pgd_end)
-#endif
LEAF(handle_tlbm)
.space FASTPATH_SIZE * 4
diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c
index 9aca10994cd..d657493ef56 100644
--- a/arch/mips/mm/tlb-r3k.c
+++ b/arch/mips/mm/tlb-r3k.c
@@ -10,7 +10,6 @@
* Copyright (C) 2002 Ralf Baechle
* Copyright (C) 2002 Maciej W. Rozycki
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 00b26a67a06..3914e27456f 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -8,6 +8,7 @@
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
*/
+#include <linux/cpu_pm.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/smp.h>
@@ -16,64 +17,44 @@
#include <linux/module.h>
#include <asm/cpu.h>
+#include <asm/cpu-type.h>
#include <asm/bootinfo.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
+#include <asm/tlb.h>
#include <asm/tlbmisc.h>
extern void build_tlb_refill_handler(void);
/*
- * Make sure all entries differ. If they're not different
- * MIPS32 will take revenge ...
+ * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
+ * unfortunately, itlb is not totally transparent to software.
*/
-#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
-
-/* Atomicity and interruptability */
-#ifdef CONFIG_MIPS_MT_SMTC
-
-#include <asm/smtc.h>
-#include <asm/mipsmtregs.h>
-
-#define ENTER_CRITICAL(flags) \
- { \
- unsigned int mvpflags; \
- local_irq_save(flags);\
- mvpflags = dvpe()
-#define EXIT_CRITICAL(flags) \
- evpe(mvpflags); \
- local_irq_restore(flags); \
+static inline void flush_itlb(void)
+{
+ switch (current_cpu_type()) {
+ case CPU_LOONGSON2:
+ case CPU_LOONGSON3:
+ write_c0_diag(4);
+ break;
+ default:
+ break;
}
-#else
-
-#define ENTER_CRITICAL(flags) local_irq_save(flags)
-#define EXIT_CRITICAL(flags) local_irq_restore(flags)
-
-#endif /* CONFIG_MIPS_MT_SMTC */
-
-#if defined(CONFIG_CPU_LOONGSON2)
-/*
- * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
- * unfortrunately, itlb is not totally transparent to software.
- */
-#define FLUSH_ITLB write_c0_diag(4);
-
-#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC) write_c0_diag(4); }
-
-#else
-
-#define FLUSH_ITLB
-#define FLUSH_ITLB_VM(vma)
+}
-#endif
+static inline void flush_itlb_vm(struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & VM_EXEC)
+ flush_itlb();
+}
void local_flush_tlb_all(void)
{
unsigned long flags;
unsigned long old_ctx;
- int entry;
+ int entry, ftlbhighset;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
write_c0_entrylo0(0);
@@ -82,18 +63,35 @@ void local_flush_tlb_all(void)
entry = read_c0_wired();
/* Blast 'em all away. */
- while (entry < current_cpu_data.tlbsize) {
- /* Make sure all entries differ. */
- write_c0_entryhi(UNIQUE_ENTRYHI(entry));
- write_c0_index(entry);
- mtc0_tlbw_hazard();
- tlb_write_indexed();
- entry++;
+ if (cpu_has_tlbinv) {
+ if (current_cpu_data.tlbsizevtlb) {
+ write_c0_index(0);
+ mtc0_tlbw_hazard();
+ tlbinvf(); /* invalidate VTLB */
+ }
+ ftlbhighset = current_cpu_data.tlbsizevtlb +
+ current_cpu_data.tlbsizeftlbsets;
+ for (entry = current_cpu_data.tlbsizevtlb;
+ entry < ftlbhighset;
+ entry++) {
+ write_c0_index(entry);
+ mtc0_tlbw_hazard();
+ tlbinvf(); /* invalidate one FTLB set */
+ }
+ } else {
+ while (entry < current_cpu_data.tlbsize) {
+ /* Make sure all entries differ. */
+ write_c0_entryhi(UNIQUE_ENTRYHI(entry));
+ write_c0_index(entry);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ entry++;
+ }
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
- FLUSH_ITLB;
- EXIT_CRITICAL(flags);
+ flush_itlb();
+ local_irq_restore(flags);
}
EXPORT_SYMBOL(local_flush_tlb_all);
@@ -123,11 +121,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
if (cpu_context(cpu, mm) != 0) {
unsigned long size, flags;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
start = round_down(start, PAGE_SIZE << 1);
end = round_up(end, PAGE_SIZE << 1);
size = (end - start) >> (PAGE_SHIFT + 1);
- if (size <= current_cpu_data.tlbsize/2) {
+ if (size <= (current_cpu_data.tlbsizeftlbsets ?
+ current_cpu_data.tlbsize / 8 :
+ current_cpu_data.tlbsize / 2)) {
int oldpid = read_c0_entryhi();
int newpid = cpu_asid(cpu, mm);
@@ -154,8 +154,8 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
} else {
drop_mmu_context(mm, cpu);
}
- FLUSH_ITLB;
- EXIT_CRITICAL(flags);
+ flush_itlb();
+ local_irq_restore(flags);
}
}
@@ -163,10 +163,12 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
unsigned long size, flags;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
size = (size + 1) >> 1;
- if (size <= current_cpu_data.tlbsize / 2) {
+ if (size <= (current_cpu_data.tlbsizeftlbsets ?
+ current_cpu_data.tlbsize / 8 :
+ current_cpu_data.tlbsize / 2)) {
int pid = read_c0_entryhi();
start &= (PAGE_MASK << 1);
@@ -196,8 +198,8 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
} else {
local_flush_tlb_all();
}
- FLUSH_ITLB;
- EXIT_CRITICAL(flags);
+ flush_itlb();
+ local_irq_restore(flags);
}
void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -210,7 +212,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
newpid = cpu_asid(cpu, vma->vm_mm);
page &= (PAGE_MASK << 1);
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
oldpid = read_c0_entryhi();
write_c0_entryhi(page | newpid);
mtc0_tlbw_hazard();
@@ -229,8 +231,8 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
finish:
write_c0_entryhi(oldpid);
- FLUSH_ITLB_VM(vma);
- EXIT_CRITICAL(flags);
+ flush_itlb_vm(vma);
+ local_irq_restore(flags);
}
}
@@ -243,7 +245,7 @@ void local_flush_tlb_one(unsigned long page)
unsigned long flags;
int oldpid, idx;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
oldpid = read_c0_entryhi();
page &= (PAGE_MASK << 1);
write_c0_entryhi(page);
@@ -261,8 +263,8 @@ void local_flush_tlb_one(unsigned long page)
tlbw_use_hazard();
}
write_c0_entryhi(oldpid);
- FLUSH_ITLB;
- EXIT_CRITICAL(flags);
+ flush_itlb();
+ local_irq_restore(flags);
}
/*
@@ -285,7 +287,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
if (current->active_mm != vma->vm_mm)
return;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
pid = read_c0_entryhi() & ASID_MASK;
address &= (PAGE_MASK << 1);
@@ -334,8 +336,8 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
tlb_write_indexed();
}
tlbw_use_hazard();
- FLUSH_ITLB_VM(vma);
- EXIT_CRITICAL(flags);
+ flush_itlb_vm(vma);
+ local_irq_restore(flags);
}
void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
@@ -346,7 +348,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
unsigned long old_pagemask;
unsigned long old_ctx;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
@@ -366,7 +368,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
tlbw_use_hazard(); /* What is the hazard here? */
write_c0_pagemask(old_pagemask);
local_flush_tlb_all();
- EXIT_CRITICAL(flags);
+ local_irq_restore(flags);
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -376,13 +378,13 @@ int __init has_transparent_hugepage(void)
unsigned int mask;
unsigned long flags;
- ENTER_CRITICAL(flags);
+ local_irq_save(flags);
write_c0_pagemask(PM_HUGE_MASK);
back_to_back_c0_hazard();
mask = read_c0_pagemask();
write_c0_pagemask(PM_DEFAULT_MASK);
- EXIT_CRITICAL(flags);
+ local_irq_restore(flags);
return mask == PM_HUGE_MASK;
}
@@ -398,7 +400,10 @@ static int __init set_ntlb(char *str)
__setup("ntlb=", set_ntlb);
-void tlb_init(void)
+/*
+ * Configure TLB (for init or after a CPU has been powered off).
+ */
+static void r4k_tlb_configure(void)
{
/*
* You should never change this register:
@@ -430,6 +435,11 @@ void tlb_init(void)
local_flush_tlb_all();
/* Did I tell you that ARC SUCKS? */
+}
+
+void tlb_init(void)
+{
+ r4k_tlb_configure();
if (ntlb) {
if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) {
@@ -443,3 +453,26 @@ void tlb_init(void)
build_tlb_refill_handler();
}
+
+static int r4k_tlb_pm_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ r4k_tlb_configure();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block r4k_tlb_pm_notifier_block = {
+ .notifier_call = r4k_tlb_pm_notifier,
+};
+
+static int __init r4k_tlb_init_pm(void)
+{
+ return cpu_pm_register_notifier(&r4k_tlb_pm_notifier_block);
+}
+arch_initcall(r4k_tlb_init_pm);
diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c
index 6a99733a444..138a2ec7cc6 100644
--- a/arch/mips/mm/tlb-r8k.c
+++ b/arch/mips/mm/tlb-r8k.c
@@ -8,7 +8,6 @@
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
*/
-#include <linux/init.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/mm.h>
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 821b45175dc..e80e10bafc8 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -26,10 +26,10 @@
#include <linux/types.h>
#include <linux/smp.h>
#include <linux/string.h>
-#include <linux/init.h>
#include <linux/cache.h>
#include <asm/cacheflush.h>
+#include <asm/cpu-type.h>
#include <asm/pgtable.h>
#include <asm/war.h>
#include <asm/uasm.h>
@@ -339,10 +339,6 @@ static struct work_registers build_get_work_registers(u32 **p)
{
struct work_registers r;
- int smp_processor_id_reg;
- int smp_processor_id_sel;
- int smp_processor_id_shift;
-
if (scratch_reg >= 0) {
/* Save in CPU local C0_KScratch? */
UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg);
@@ -353,25 +349,9 @@ static struct work_registers build_get_work_registers(u32 **p)
}
if (num_possible_cpus() > 1) {
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
- smp_processor_id_shift = 51;
- smp_processor_id_reg = 20; /* XContext */
- smp_processor_id_sel = 0;
-#else
-# ifdef CONFIG_32BIT
- smp_processor_id_shift = 25;
- smp_processor_id_reg = 4; /* Context */
- smp_processor_id_sel = 0;
-# endif
-# ifdef CONFIG_64BIT
- smp_processor_id_shift = 26;
- smp_processor_id_reg = 4; /* Context */
- smp_processor_id_sel = 0;
-# endif
-#endif
/* Get smp_processor_id */
- UASM_i_MFC0(p, K0, smp_processor_id_reg, smp_processor_id_sel);
- UASM_i_SRL_SAFE(p, K0, K0, smp_processor_id_shift);
+ UASM_i_CPUID_MFC0(p, K0, SMP_CPUID_REG);
+ UASM_i_SRL_SAFE(p, K0, K0, SMP_CPUID_REGSHIFT);
/* handler_reg_save index in K0 */
UASM_i_SLL(p, K0, K0, ilog2(sizeof(struct tlb_reg_save)));
@@ -529,6 +509,10 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
switch (current_cpu_type()) {
case CPU_M14KC:
case CPU_74K:
+ case CPU_1074K:
+ case CPU_PROAPTIV:
+ case CPU_P5600:
+ case CPU_M5150:
break;
default:
@@ -598,6 +582,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
case CPU_BMIPS4380:
case CPU_BMIPS5000:
case CPU_LOONGSON2:
+ case CPU_LOONGSON3:
case CPU_R5500:
if (m4kc_tlbp_war())
uasm_i_nop(p);
@@ -640,7 +625,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
default:
panic("No TLB refill handler yet (CPU type: %d)",
- current_cpu_data.cputype);
+ current_cpu_type());
break;
}
}
@@ -818,11 +803,11 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
}
/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
if (pgd_reg != -1) {
/* pgd is in pgd_reg */
UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
} else {
+#if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
/*
* &pgd << 11 stored in CONTEXT [23..63].
*/
@@ -834,30 +819,18 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
/* 1 0 1 0 1 << 6 xkphys cached */
uasm_i_ori(p, ptr, ptr, 0x540);
uasm_i_drotr(p, ptr, ptr, 11);
- }
#elif defined(CONFIG_SMP)
-# ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC uses TCBind value as "CPU" index
- */
- uasm_i_mfc0(p, ptr, C0_TCBIND);
- uasm_i_dsrl_safe(p, ptr, ptr, 19);
-# else
- /*
- * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
- * stored in CONTEXT.
- */
- uasm_i_dmfc0(p, ptr, C0_CONTEXT);
- uasm_i_dsrl_safe(p, ptr, ptr, 23);
-# endif
- UASM_i_LA_mostly(p, tmp, pgdc);
- uasm_i_daddu(p, ptr, ptr, tmp);
- uasm_i_dmfc0(p, tmp, C0_BADVADDR);
- uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+ UASM_i_CPUID_MFC0(p, ptr, SMP_CPUID_REG);
+ uasm_i_dsrl_safe(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
+ UASM_i_LA_mostly(p, tmp, pgdc);
+ uasm_i_daddu(p, ptr, ptr, tmp);
+ uasm_i_dmfc0(p, tmp, C0_BADVADDR);
+ uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
#else
- UASM_i_LA_mostly(p, ptr, pgdc);
- uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+ UASM_i_LA_mostly(p, ptr, pgdc);
+ uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
#endif
+ }
uasm_l_vmalloc_done(l, *p);
@@ -952,31 +925,25 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
static void __maybe_unused
build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
{
- long pgdc = (long)pgd_current;
+ if (pgd_reg != -1) {
+ /* pgd is in pgd_reg */
+ uasm_i_mfc0(p, ptr, c0_kscratch(), pgd_reg);
+ uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+ } else {
+ long pgdc = (long)pgd_current;
- /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
+ /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
#ifdef CONFIG_SMP
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC uses TCBind value as "CPU" index
- */
- uasm_i_mfc0(p, ptr, C0_TCBIND);
- UASM_i_LA_mostly(p, tmp, pgdc);
- uasm_i_srl(p, ptr, ptr, 19);
-#else
- /*
- * smp_processor_id() << 2 is stored in CONTEXT.
- */
- uasm_i_mfc0(p, ptr, C0_CONTEXT);
- UASM_i_LA_mostly(p, tmp, pgdc);
- uasm_i_srl(p, ptr, ptr, 23);
-#endif
- uasm_i_addu(p, ptr, tmp, ptr);
+ uasm_i_mfc0(p, ptr, SMP_CPUID_REG);
+ UASM_i_LA_mostly(p, tmp, pgdc);
+ uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
+ uasm_i_addu(p, ptr, tmp, ptr);
#else
- UASM_i_LA_mostly(p, ptr, pgdc);
+ UASM_i_LA_mostly(p, ptr, pgdc);
#endif
- uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
- uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+ uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+ uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+ }
uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -1289,7 +1256,7 @@ static void build_r4000_tlb_refill_handler(void)
memset(relocs, 0, sizeof(relocs));
memset(final_handler, 0, sizeof(final_handler));
- if ((scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) {
+ if (IS_ENABLED(CONFIG_64BIT) && (scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) {
htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
scratch_reg);
vmalloc_mode = refill_scratch;
@@ -1348,95 +1315,100 @@ static void build_r4000_tlb_refill_handler(void)
* need three, with the second nop'ed and the third being
* unused.
*/
- /* Loongson2 ebase is different than r4k, we have more space */
-#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
- if ((p - tlb_handler) > 64)
- panic("TLB refill handler space exceeded");
-#else
- if (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 1)
- || (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 3)
- && uasm_insn_has_bdelay(relocs,
- tlb_handler + MIPS64_REFILL_INSNS - 3)))
- panic("TLB refill handler space exceeded");
-#endif
-
- /*
- * Now fold the handler in the TLB refill handler space.
- */
-#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
- f = final_handler;
- /* Simplest case, just copy the handler. */
- uasm_copy_handler(relocs, labels, tlb_handler, p, f);
- final_len = p - tlb_handler;
-#else /* CONFIG_64BIT */
- f = final_handler + MIPS64_REFILL_INSNS;
- if ((p - tlb_handler) <= MIPS64_REFILL_INSNS) {
- /* Just copy the handler. */
- uasm_copy_handler(relocs, labels, tlb_handler, p, f);
- final_len = p - tlb_handler;
- } else {
-#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
- const enum label_id ls = label_tlb_huge_update;
-#else
- const enum label_id ls = label_vmalloc;
-#endif
- u32 *split;
- int ov = 0;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(labels) && labels[i].lab != ls; i++)
- ;
- BUG_ON(i == ARRAY_SIZE(labels));
- split = labels[i].addr;
-
- /*
- * See if we have overflown one way or the other.
- */
- if (split > tlb_handler + MIPS64_REFILL_INSNS ||
- split < p - MIPS64_REFILL_INSNS)
- ov = 1;
-
- if (ov) {
+ switch (boot_cpu_type()) {
+ default:
+ if (sizeof(long) == 4) {
+ case CPU_LOONGSON2:
+ /* Loongson2 ebase is different than r4k, we have more space */
+ if ((p - tlb_handler) > 64)
+ panic("TLB refill handler space exceeded");
/*
- * Split two instructions before the end. One
- * for the branch and one for the instruction
- * in the delay slot.
+ * Now fold the handler in the TLB refill handler space.
*/
- split = tlb_handler + MIPS64_REFILL_INSNS - 2;
-
+ f = final_handler;
+ /* Simplest case, just copy the handler. */
+ uasm_copy_handler(relocs, labels, tlb_handler, p, f);
+ final_len = p - tlb_handler;
+ break;
+ } else {
+ if (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 1)
+ || (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 3)
+ && uasm_insn_has_bdelay(relocs,
+ tlb_handler + MIPS64_REFILL_INSNS - 3)))
+ panic("TLB refill handler space exceeded");
/*
- * If the branch would fall in a delay slot,
- * we must back up an additional instruction
- * so that it is no longer in a delay slot.
+ * Now fold the handler in the TLB refill handler space.
*/
- if (uasm_insn_has_bdelay(relocs, split - 1))
- split--;
- }
- /* Copy first part of the handler. */
- uasm_copy_handler(relocs, labels, tlb_handler, split, f);
- f += split - tlb_handler;
-
- if (ov) {
- /* Insert branch. */
- uasm_l_split(&l, final_handler);
- uasm_il_b(&f, &r, label_split);
- if (uasm_insn_has_bdelay(relocs, split))
- uasm_i_nop(&f);
- else {
- uasm_copy_handler(relocs, labels,
- split, split + 1, f);
- uasm_move_labels(labels, f, f + 1, -1);
- f++;
- split++;
+ f = final_handler + MIPS64_REFILL_INSNS;
+ if ((p - tlb_handler) <= MIPS64_REFILL_INSNS) {
+ /* Just copy the handler. */
+ uasm_copy_handler(relocs, labels, tlb_handler, p, f);
+ final_len = p - tlb_handler;
+ } else {
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+ const enum label_id ls = label_tlb_huge_update;
+#else
+ const enum label_id ls = label_vmalloc;
+#endif
+ u32 *split;
+ int ov = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(labels) && labels[i].lab != ls; i++)
+ ;
+ BUG_ON(i == ARRAY_SIZE(labels));
+ split = labels[i].addr;
+
+ /*
+ * See if we have overflown one way or the other.
+ */
+ if (split > tlb_handler + MIPS64_REFILL_INSNS ||
+ split < p - MIPS64_REFILL_INSNS)
+ ov = 1;
+
+ if (ov) {
+ /*
+ * Split two instructions before the end. One
+ * for the branch and one for the instruction
+ * in the delay slot.
+ */
+ split = tlb_handler + MIPS64_REFILL_INSNS - 2;
+
+ /*
+ * If the branch would fall in a delay slot,
+ * we must back up an additional instruction
+ * so that it is no longer in a delay slot.
+ */
+ if (uasm_insn_has_bdelay(relocs, split - 1))
+ split--;
+ }
+ /* Copy first part of the handler. */
+ uasm_copy_handler(relocs, labels, tlb_handler, split, f);
+ f += split - tlb_handler;
+
+ if (ov) {
+ /* Insert branch. */
+ uasm_l_split(&l, final_handler);
+ uasm_il_b(&f, &r, label_split);
+ if (uasm_insn_has_bdelay(relocs, split))
+ uasm_i_nop(&f);
+ else {
+ uasm_copy_handler(relocs, labels,
+ split, split + 1, f);
+ uasm_move_labels(labels, f, f + 1, -1);
+ f++;
+ split++;
+ }
+ }
+
+ /* Copy the rest of the handler. */
+ uasm_copy_handler(relocs, labels, split, p, final_handler);
+ final_len = (f - (final_handler + MIPS64_REFILL_INSNS)) +
+ (p - split);
}
}
-
- /* Copy the rest of the handler. */
- uasm_copy_handler(relocs, labels, split, p, final_handler);
- final_len = (f - (final_handler + MIPS64_REFILL_INSNS)) +
- (p - split);
+ break;
}
-#endif /* CONFIG_64BIT */
uasm_resolve_relocs(relocs, labels);
pr_debug("Wrote TLB refill handler (%u instructions).\n",
@@ -1450,28 +1422,31 @@ static void build_r4000_tlb_refill_handler(void)
extern u32 handle_tlbl[], handle_tlbl_end[];
extern u32 handle_tlbs[], handle_tlbs_end[];
extern u32 handle_tlbm[], handle_tlbm_end[];
+extern u32 tlbmiss_handler_setup_pgd_start[], tlbmiss_handler_setup_pgd[];
+extern u32 tlbmiss_handler_setup_pgd_end[];
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[];
-
-static void build_r4000_setup_pgd(void)
+static void build_setup_pgd(void)
{
const int a0 = 4;
- const int a1 = 5;
- u32 *p = tlbmiss_handler_setup_pgd;
+ const int __maybe_unused a1 = 5;
+ const int __maybe_unused a2 = 6;
+ u32 *p = tlbmiss_handler_setup_pgd_start;
const int tlbmiss_handler_setup_pgd_size =
- tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd;
- struct uasm_label *l = labels;
- struct uasm_reloc *r = relocs;
+ tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd_start;
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+ long pgdc = (long)pgd_current;
+#endif
memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
sizeof(tlbmiss_handler_setup_pgd[0]));
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
-
pgd_reg = allocate_kscratch();
-
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
if (pgd_reg == -1) {
+ struct uasm_label *l = labels;
+ struct uasm_reloc *r = relocs;
+
/* PGD << 11 in c0_Context */
/*
* If it is a ckseg0 address, convert to a physical
@@ -1493,6 +1468,26 @@ static void build_r4000_setup_pgd(void)
uasm_i_jr(&p, 31);
UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
}
+#else
+#ifdef CONFIG_SMP
+ /* Save PGD to pgd_current[smp_processor_id()] */
+ UASM_i_CPUID_MFC0(&p, a1, SMP_CPUID_REG);
+ UASM_i_SRL_SAFE(&p, a1, a1, SMP_CPUID_PTRSHIFT);
+ UASM_i_LA_mostly(&p, a2, pgdc);
+ UASM_i_ADDU(&p, a2, a2, a1);
+ UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#else
+ UASM_i_LA_mostly(&p, a2, pgdc);
+ UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#endif /* SMP */
+ uasm_i_jr(&p, 31);
+
+ /* if pgd_reg is allocated, save PGD also to scratch register */
+ if (pgd_reg != -1)
+ UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+ else
+ uasm_i_nop(&p);
+#endif
if (p >= tlbmiss_handler_setup_pgd_end)
panic("tlbmiss_handler_setup_pgd space exceeded");
@@ -1503,7 +1498,6 @@ static void build_r4000_setup_pgd(void)
dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
tlbmiss_handler_setup_pgd_size);
}
-#endif
static void
iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -2196,10 +2190,8 @@ static void flush_tlb_handlers(void)
(unsigned long)handle_tlbs_end);
local_flush_icache_range((unsigned long)handle_tlbm,
(unsigned long)handle_tlbm_end);
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
(unsigned long)tlbmiss_handler_setup_pgd_end);
-#endif
}
void build_tlb_refill_handler(void)
@@ -2231,6 +2223,7 @@ void build_tlb_refill_handler(void)
if (!run_once) {
if (!cpu_has_local_ebase)
build_r3000_tlb_refill_handler();
+ build_setup_pgd();
build_r3000_tlb_load_handler();
build_r3000_tlb_store_handler();
build_r3000_tlb_modify_handler();
@@ -2254,9 +2247,7 @@ void build_tlb_refill_handler(void)
default:
if (!run_once) {
scratch_reg = allocate_kscratch();
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
- build_r4000_setup_pgd();
-#endif
+ build_setup_pgd();
build_r4000_tlb_load_handler();
build_r4000_tlb_store_handler();
build_r4000_tlb_modify_handler();
diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c
index 060000fa653..8399ddf03a0 100644
--- a/arch/mips/mm/uasm-micromips.c
+++ b/arch/mips/mm/uasm-micromips.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/init.h>
#include <asm/inst.h>
#include <asm/elf.h>
@@ -64,6 +63,7 @@ static struct insn insn_table_MM[] = {
{ insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM },
{ insn_daddu, 0, 0 },
{ insn_daddiu, 0, 0 },
+ { insn_divu, M(mm_pool32a_op, 0, 0, 0, mm_divu_op, mm_pool32axf_op), RT | RS },
{ insn_dmfc0, 0, 0 },
{ insn_dmtc0, 0, 0 },
{ insn_dsll, 0, 0 },
@@ -79,14 +79,20 @@ static struct insn insn_table_MM[] = {
{ insn_ext, M(mm_pool32a_op, 0, 0, 0, 0, mm_ext_op), RT | RS | RD | RE },
{ insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM },
{ insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM },
+ { insn_jalr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RT | RS },
{ insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS },
+ { insn_lb, M(mm_lb32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
{ insn_ld, 0, 0 },
+ { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RS | RS | SIMM },
{ insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM },
{ insn_lld, 0, 0 },
{ insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM },
{ insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
{ insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD },
+ { insn_mfhi, M(mm_pool32a_op, 0, 0, 0, mm_mfhi32_op, mm_pool32axf_op), RS },
+ { insn_mflo, M(mm_pool32a_op, 0, 0, 0, mm_mflo32_op, mm_pool32axf_op), RS },
{ insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD },
+ { insn_mul, M(mm_pool32a_op, 0, 0, 0, 0, mm_mul_op), RT | RS | RD },
{ insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD },
{ insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
{ insn_pref, M(mm_pool32c_op, 0, 0, (mm_pref_func << 1), 0, 0), RT | RS | SIMM },
@@ -95,15 +101,23 @@ static struct insn insn_table_MM[] = {
{ insn_scd, 0, 0 },
{ insn_sd, 0, 0 },
{ insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD },
+ { insn_sllv, M(mm_pool32a_op, 0, 0, 0, 0, mm_sllv32_op), RT | RS | RD },
+ { insn_slt, M(mm_pool32a_op, 0, 0, 0, 0, mm_slt_op), RT | RS | RD },
+ { insn_sltiu, M(mm_sltiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
+ { insn_sltu, M(mm_pool32a_op, 0, 0, 0, 0, mm_sltu_op), RT | RS | RD },
{ insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD },
{ insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD },
+ { insn_srlv, M(mm_pool32a_op, 0, 0, 0, 0, mm_srlv32_op), RT | RS | RD },
{ insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD },
{ insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD },
{ insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM },
+ { insn_sync, M(mm_pool32a_op, 0, 0, 0, mm_sync_op, mm_pool32axf_op), RS },
{ insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 },
{ insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 },
{ insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 },
{ insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 },
+ { insn_wait, M(mm_pool32a_op, 0, 0, 0, mm_wait_op, mm_pool32axf_op), SCIMM },
+ { insn_wsbh, M(mm_pool32a_op, 0, 0, 0, mm_wsbh_op, mm_pool32axf_op), RT | RS },
{ insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD },
{ insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM },
{ insn_dins, 0, 0 },
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index 0c724589854..6708a2dbf93 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/init.h>
#include <asm/inst.h>
#include <asm/elf.h>
@@ -68,6 +67,7 @@ static struct insn insn_table[] = {
{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
+ { insn_divu, M(spec_op, 0, 0, 0, 0, divu_op), RS | RT },
{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
@@ -83,17 +83,23 @@ static struct insn insn_table[] = {
{ insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
{ insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
+ { insn_jalr, M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD },
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
{ insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
+ { insn_lb, M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
+ { insn_lh, M(lh_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
{ insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
{ insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_mfhi, M(spec_op, 0, 0, 0, 0, mfhi_op), RD },
+ { insn_mflo, M(spec_op, 0, 0, 0, 0, mflo_op), RD },
{ insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
+ { insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
{ insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
{ insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
@@ -103,17 +109,26 @@ static struct insn insn_table[] = {
{ insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
+ { insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD },
+ { insn_slt, M(spec_op, 0, 0, 0, 0, slt_op), RS | RT | RD },
+ { insn_sltiu, M(sltiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_sltu, M(spec_op, 0, 0, 0, 0, sltu_op), RS | RT | RD },
{ insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
{ insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
+ { insn_srlv, M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD },
{ insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
{ insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
+ { insn_sync, M(spec_op, 0, 0, 0, 0, sync_op), RE },
{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
{ insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
{ insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 },
{ insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
{ insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
+ { insn_wait, M(cop0_op, cop_op, 0, 0, 0, wait_op), SCIMM },
+ { insn_wsbh, M(spec3_op, 0, 0, 0, wsbh_op, bshfl_op), RT | RD },
{ insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
+ { insn_yield, M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD },
{ insn_invalid, 0, 0 }
};
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index b9d14b6c7f5..a01b0d6cedd 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -47,14 +47,16 @@ enum opcode {
insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1,
insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm,
- insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll,
+ insn_divu, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll,
insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret,
- insn_ext, insn_ins, insn_j, insn_jal, insn_jr, insn_ld, insn_ldx,
- insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0,
+ insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_lb,
+ insn_ld, insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw,
+ insn_lwx, insn_mfc0, insn_mfhi, insn_mflo, insn_mtc0, insn_mul,
insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd,
- insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
- insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor,
- insn_xori,
+ insn_sd, insn_sll, insn_sllv, insn_slt, insn_sltiu, insn_sltu, insn_sra,
+ insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall,
+ insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh,
+ insn_xor, insn_xori, insn_yield,
};
struct insn {
@@ -137,6 +139,13 @@ Ip_u1u2u3(op) \
} \
UASM_EXPORT_SYMBOL(uasm_i##op);
+#define I_s3s1s2(op) \
+Ip_s3s1s2(op) \
+{ \
+ build_insn(buf, insn##op, b, c, a); \
+} \
+UASM_EXPORT_SYMBOL(uasm_i##op);
+
#define I_u2u1u3(op) \
Ip_u2u1u3(op) \
{ \
@@ -144,6 +153,13 @@ Ip_u2u1u3(op) \
} \
UASM_EXPORT_SYMBOL(uasm_i##op);
+#define I_u3u2u1(op) \
+Ip_u3u2u1(op) \
+{ \
+ build_insn(buf, insn##op, c, b, a); \
+} \
+UASM_EXPORT_SYMBOL(uasm_i##op);
+
#define I_u3u1u2(op) \
Ip_u3u1u2(op) \
{ \
@@ -200,6 +216,13 @@ Ip_u1u2(op) \
} \
UASM_EXPORT_SYMBOL(uasm_i##op);
+#define I_u2u1(op) \
+Ip_u1u2(op) \
+{ \
+ build_insn(buf, insn##op, b, a); \
+} \
+UASM_EXPORT_SYMBOL(uasm_i##op);
+
#define I_u1s2(op) \
Ip_u1s2(op) \
{ \
@@ -237,6 +260,7 @@ I_u1u2u3(_dmfc0)
I_u1u2u3(_dmtc0)
I_u2u1s3(_daddiu)
I_u3u1u2(_daddu)
+I_u1u2(_divu)
I_u2u1u3(_dsll)
I_u2u1u3(_dsll32)
I_u2u1u3(_dsra)
@@ -250,14 +274,20 @@ I_u2u1msbdu3(_ext)
I_u2u1msbu3(_ins)
I_u1(_j)
I_u1(_jal)
+I_u2u1(_jalr)
I_u1(_jr)
+I_u2s3u1(_lb)
I_u2s3u1(_ld)
+I_u2s3u1(_lh)
I_u2s3u1(_ll)
I_u2s3u1(_lld)
I_u1s2(_lui)
I_u2s3u1(_lw)
I_u1u2u3(_mfc0)
+I_u1(_mfhi)
+I_u1(_mflo)
I_u1u2u3(_mtc0)
+I_u3u1u2(_mul)
I_u2u1u3(_ori)
I_u3u1u2(_or)
I_0(_rfe)
@@ -265,17 +295,26 @@ I_u2s3u1(_sc)
I_u2s3u1(_scd)
I_u2s3u1(_sd)
I_u2u1u3(_sll)
+I_u3u2u1(_sllv)
+I_s3s1s2(_slt)
+I_u2u1s3(_sltiu)
+I_u3u1u2(_sltu)
I_u2u1u3(_sra)
I_u2u1u3(_srl)
+I_u3u2u1(_srlv)
I_u2u1u3(_rotr)
I_u3u1u2(_subu)
I_u2s3u1(_sw)
+I_u1(_sync)
I_0(_tlbp)
I_0(_tlbr)
I_0(_tlbwi)
I_0(_tlbwr)
+I_u1(_wait);
+I_u2u1(_wsbh)
I_u3u1u2(_xor)
I_u2u1u3(_xori)
+I_u2u1(_yield)
I_u2u1msbu3(_dins);
I_u2u1msb32u3(_dinsm);
I_u1(_syscall);
@@ -469,6 +508,14 @@ void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid)
}
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b));
+void ISAFUNC(uasm_il_beq)(u32 **p, struct uasm_reloc **r, unsigned int r1,
+ unsigned int r2, int lid)
+{
+ uasm_r_mips_pc16(r, *p, lid);
+ ISAFUNC(uasm_i_beq)(p, r1, r2, 0);
+}
+UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq));
+
void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg,
int lid)
{
diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile
index 72fdedbf76d..b9510ea8db5 100644
--- a/arch/mips/mti-malta/Makefile
+++ b/arch/mips/mti-malta/Makefile
@@ -9,7 +9,4 @@ obj-y := malta-amon.o malta-display.o malta-init.o \
malta-int.o malta-memory.o malta-platform.o \
malta-reset.o malta-setup.o malta-time.o
-obj-$(CONFIG_EARLY_PRINTK) += malta-console.o
-
-# FIXME FIXME FIXME
-obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o
+obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o
diff --git a/arch/mips/mti-malta/malta-amon.c b/arch/mips/mti-malta/malta-amon.c
index 1e478445801..84ac523b0ce 100644
--- a/arch/mips/mti-malta/malta-amon.c
+++ b/arch/mips/mti-malta/malta-amon.c
@@ -1,30 +1,20 @@
/*
- * Copyright (C) 2007 MIPS Technologies, Inc.
- * All rights reserved.
-
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * Copyright (C) 2007 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*
- * Arbitrary Monitor interface
+ * Arbitrary Monitor Interface
*/
-
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/smp.h>
#include <asm/addrspace.h>
-#include <asm/mips-boards/launch.h>
#include <asm/mipsmtregs.h>
+#include <asm/mips-boards/launch.h>
+#include <asm/vpe.h>
int amon_cpu_avail(int cpu)
{
@@ -48,7 +38,7 @@ int amon_cpu_avail(int cpu)
return 1;
}
-void amon_cpu_start(int cpu,
+int amon_cpu_start(int cpu,
unsigned long pc, unsigned long sp,
unsigned long gp, unsigned long a0)
{
@@ -56,10 +46,10 @@ void amon_cpu_start(int cpu,
(struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
if (!amon_cpu_avail(cpu))
- return;
+ return -1;
if (cpu == smp_processor_id()) {
pr_debug("launch: I am cpu%d!\n", cpu);
- return;
+ return -1;
}
launch += cpu;
@@ -78,4 +68,21 @@ void amon_cpu_start(int cpu,
;
smp_rmb(); /* Target will be updating flags soon */
pr_debug("launch: cpu%d gone!\n", cpu);
+
+ return 0;
+}
+
+#ifdef CONFIG_MIPS_VPE_LOADER_CMP
+int vpe_run(struct vpe *v)
+{
+ struct vpe_notifications *n;
+
+ if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0)
+ return -1;
+
+ list_for_each_entry(n, &v->notify, list)
+ n->start(VPE_MODULE_MINOR);
+
+ return 0;
}
+#endif
diff --git a/arch/mips/mti-malta/malta-console.c b/arch/mips/mti-malta/malta-console.c
deleted file mode 100644
index 43bcfb4f816..00000000000
--- a/arch/mips/mti-malta/malta-console.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Putting things on the screen/serial line using YAMONs facilities.
- */
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/serial_reg.h>
-#include <asm/io.h>
-
-
-#define PORT(offset) (0x3f8 + (offset))
-
-
-static inline unsigned int serial_in(int offset)
-{
- return inb(PORT(offset));
-}
-
-static inline void serial_out(int offset, int value)
-{
- outb(value, PORT(offset));
-}
-
-int prom_putchar(char c)
-{
- while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
- ;
-
- serial_out(UART_TX, c);
-
- return 1;
-}
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index ff8caffd326..0f60256d378 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -14,12 +14,14 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/serial_8250.h>
#include <asm/cacheflush.h>
#include <asm/smp-ops.h>
#include <asm/traps.h>
#include <asm/fw/fw.h>
-#include <asm/gcmpregs.h>
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/malta.h>
@@ -44,32 +46,39 @@ static void __init console_config(void)
char parity = '\0', bits = '\0', flow = '\0';
char *s;
- if ((strstr(fw_getcmdline(), "console=")) == NULL) {
- s = fw_getenv("modetty0");
- if (s) {
- while (*s >= '0' && *s <= '9')
- baud = baud*10 + *s++ - '0';
- if (*s == ',')
- s++;
- if (*s)
- parity = *s++;
- if (*s == ',')
- s++;
- if (*s)
- bits = *s++;
- if (*s == ',')
- s++;
- if (*s == 'h')
- flow = 'r';
- }
- if (baud == 0)
- baud = 38400;
- if (parity != 'n' && parity != 'o' && parity != 'e')
- parity = 'n';
- if (bits != '7' && bits != '8')
- bits = '8';
- if (flow == '\0')
+ s = fw_getenv("modetty0");
+ if (s) {
+ while (*s >= '0' && *s <= '9')
+ baud = baud*10 + *s++ - '0';
+ if (*s == ',')
+ s++;
+ if (*s)
+ parity = *s++;
+ if (*s == ',')
+ s++;
+ if (*s)
+ bits = *s++;
+ if (*s == ',')
+ s++;
+ if (*s == 'h')
flow = 'r';
+ }
+ if (baud == 0)
+ baud = 38400;
+ if (parity != 'n' && parity != 'o' && parity != 'e')
+ parity = 'n';
+ if (bits != '7' && bits != '8')
+ bits = '8';
+ if (flow == '\0')
+ flow = 'r';
+
+ if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) {
+ sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud,
+ parity, bits);
+ setup_early_serial8250_console(console_string);
+ }
+
+ if ((strstr(fw_getcmdline(), "console=")) == NULL) {
sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
parity, bits, flow);
strcat(fw_getcmdline(), console_string);
@@ -102,7 +111,10 @@ static void __init mips_ejtag_setup(void)
flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
}
-extern struct plat_smp_ops msmtc_smp_ops;
+phys_t mips_cpc_default_phys_base(void)
+{
+ return CPC_BASE_ADDR;
+}
void __init prom_init(void)
{
@@ -230,10 +242,23 @@ mips_pci_controller:
MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
#endif
+#ifndef CONFIG_EVA
/* Fix up target memory mapping. */
MSC_READ(MSC01_PCI_BAR0, mask);
MSC_WRITE(MSC01_PCI_P2SCMSKL, mask & MSC01_PCI_BAR0_SIZE_MSK);
+#else
+ /*
+ * Setup the Malta max (2GB) memory for PCI DMA in host bridge
+ * in transparent addressing mode, starting from 0x80000000.
+ */
+ mask = PHYS_OFFSET | (1<<3);
+ MSC_WRITE(MSC01_PCI_BAR0, mask);
+ mask = PHYS_OFFSET;
+ MSC_WRITE(MSC01_PCI_HEAD4, mask);
+ MSC_WRITE(MSC01_PCI_P2SCMSKL, mask);
+ MSC_WRITE(MSC01_PCI_P2SCMAPL, mask);
+#endif
/* Don't handle target retries indefinitely. */
if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) ==
MSC01_PCI_CFG_MAXRTRY_MSK)
@@ -268,14 +293,13 @@ mips_pci_controller:
console_config();
#endif
/* Early detection of CMP support */
- if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))
- if (!register_cmp_smp_ops())
- return;
+ mips_cm_probe();
+ mips_cpc_probe();
+ if (!register_cps_smp_ops())
+ return;
+ if (!register_cmp_smp_ops())
+ return;
if (!register_vsmp_smp_ops())
return;
-
-#ifdef CONFIG_MIPS_MT_SMTC
- register_smp_ops(&msmtc_smp_ops);
-#endif
}
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index c69da373469..ecc2785f785 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -1,25 +1,16 @@
/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
* Copyright (C) 2001 Ralf Baechle
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*
* Routines for generic manipulation of the interrupts found on the MIPS
- * Malta board.
- * The interrupt controller is located in the South Bridge a PIIX4 device
- * with two internal 82C95 interrupt controllers.
+ * Malta board. The interrupt controller is located in the South Bridge
+ * a PIIX4 device with two internal 82C95 interrupt controllers.
*/
#include <linux/init.h>
#include <linux/irq.h>
@@ -35,20 +26,18 @@
#include <asm/i8259.h>
#include <asm/irq_cpu.h>
#include <asm/irq_regs.h>
+#include <asm/mips-cm.h>
#include <asm/mips-boards/malta.h>
#include <asm/mips-boards/maltaint.h>
-#include <asm/mips-boards/piix4.h>
#include <asm/gt64120.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/msc01_pci.h>
#include <asm/msc01_ic.h>
#include <asm/gic.h>
-#include <asm/gcmpregs.h>
#include <asm/setup.h>
+#include <asm/rtlx.h>
-int gcmp_present = -1;
static unsigned long _msc01_biu_base;
-static unsigned long _gcmp_base;
static unsigned int ipi_map[NR_CPUS];
static DEFINE_RAW_SPINLOCK(mips_irq_lock);
@@ -91,7 +80,7 @@ static inline int mips_pcibios_iack(void)
BONITO_PCIMAP_CFG = 0;
break;
default:
- printk(KERN_WARNING "Unknown system controller.\n");
+ pr_emerg("Unknown system controller.\n");
return -1;
}
return irq;
@@ -127,6 +116,11 @@ static void malta_hw0_irqdispatch(void)
}
do_IRQ(MALTA_INT_BASE + irq);
+
+#ifdef CONFIG_MIPS_VPE_APSP_API_MT
+ if (aprp_hook)
+ aprp_hook();
+#endif
}
static void malta_ipi_irqdispatch(void)
@@ -150,11 +144,11 @@ static void corehi_irqdispatch(void)
unsigned int intrcause, datalo, datahi;
struct pt_regs *regs = get_irq_regs();
- printk(KERN_EMERG "CoreHI interrupt, shouldn't happen, we die here!\n");
- printk(KERN_EMERG "epc : %08lx\nStatus: %08lx\n"
- "Cause : %08lx\nbadVaddr : %08lx\n",
- regs->cp0_epc, regs->cp0_status,
- regs->cp0_cause, regs->cp0_badvaddr);
+ pr_emerg("CoreHI interrupt, shouldn't happen, we die here!\n");
+ pr_emerg("epc : %08lx\nStatus: %08lx\n"
+ "Cause : %08lx\nbadVaddr : %08lx\n",
+ regs->cp0_epc, regs->cp0_status,
+ regs->cp0_cause, regs->cp0_badvaddr);
/* Read all the registers and then print them as there is a
problem with interspersed printk's upsetting the Bonito controller.
@@ -172,8 +166,8 @@ static void corehi_irqdispatch(void)
intrcause = GT_READ(GT_INTRCAUSE_OFS);
datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
- printk(KERN_EMERG "GT_INTRCAUSE = %08x\n", intrcause);
- printk(KERN_EMERG "GT_CPUERR_ADDR = %02x%08x\n",
+ pr_emerg("GT_INTRCAUSE = %08x\n", intrcause);
+ pr_emerg("GT_CPUERR_ADDR = %02x%08x\n",
datahi, datalo);
break;
case MIPS_REVISION_SCON_BONITO:
@@ -185,14 +179,14 @@ static void corehi_irqdispatch(void)
intedge = BONITO_INTEDGE;
intsteer = BONITO_INTSTEER;
pcicmd = BONITO_PCICMD;
- printk(KERN_EMERG "BONITO_INTISR = %08x\n", intisr);
- printk(KERN_EMERG "BONITO_INTEN = %08x\n", inten);
- printk(KERN_EMERG "BONITO_INTPOL = %08x\n", intpol);
- printk(KERN_EMERG "BONITO_INTEDGE = %08x\n", intedge);
- printk(KERN_EMERG "BONITO_INTSTEER = %08x\n", intsteer);
- printk(KERN_EMERG "BONITO_PCICMD = %08x\n", pcicmd);
- printk(KERN_EMERG "BONITO_PCIBADADDR = %08x\n", pcibadaddr);
- printk(KERN_EMERG "BONITO_PCIMSTAT = %08x\n", pcimstat);
+ pr_emerg("BONITO_INTISR = %08x\n", intisr);
+ pr_emerg("BONITO_INTEN = %08x\n", inten);
+ pr_emerg("BONITO_INTPOL = %08x\n", intpol);
+ pr_emerg("BONITO_INTEDGE = %08x\n", intedge);
+ pr_emerg("BONITO_INTSTEER = %08x\n", intsteer);
+ pr_emerg("BONITO_PCICMD = %08x\n", pcicmd);
+ pr_emerg("BONITO_PCIBADADDR = %08x\n", pcibadaddr);
+ pr_emerg("BONITO_PCIMSTAT = %08x\n", pcimstat);
break;
}
@@ -292,10 +286,6 @@ asmlinkage void plat_irq_dispatch(void)
#ifdef CONFIG_MIPS_MT_SMP
-
-#define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3
-#define GIC_MIPS_CPU_IPI_CALL_IRQ 4
-
#define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */
#define C_RESCHED C_SW0
#define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for resched */
@@ -312,8 +302,20 @@ static void ipi_call_dispatch(void)
do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
}
+#endif /* CONFIG_MIPS_MT_SMP */
+
+#ifdef CONFIG_MIPS_GIC_IPI
+
+#define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3
+#define GIC_MIPS_CPU_IPI_CALL_IRQ 4
+
static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
{
+#ifdef CONFIG_MIPS_VPE_APSP_API_CMP
+ if (aprp_hook)
+ aprp_hook();
+#endif
+
scheduler_ipi();
return IRQ_HANDLED;
@@ -337,7 +339,7 @@ static struct irqaction irq_call = {
.flags = IRQF_PERCPU,
.name = "IPI_call"
};
-#endif /* CONFIG_MIPS_MT_SMP */
+#endif /* CONFIG_MIPS_GIC_IPI */
static int gic_resched_int_base;
static int gic_call_int_base;
@@ -366,13 +368,13 @@ static struct irqaction corehi_irqaction = {
.flags = IRQF_NO_THREAD,
};
-static msc_irqmap_t __initdata msc_irqmap[] = {
+static msc_irqmap_t msc_irqmap[] __initdata = {
{MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0},
{MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0},
};
-static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
+static int msc_nr_irqs __initdata = ARRAY_SIZE(msc_irqmap);
-static msc_irqmap_t __initdata msc_eicirqmap[] = {
+static msc_irqmap_t msc_eicirqmap[] __initdata = {
{MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0},
{MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0},
{MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0},
@@ -385,7 +387,7 @@ static msc_irqmap_t __initdata msc_eicirqmap[] = {
{MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0}
};
-static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
+static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap);
/*
* This GIC specific tabular array defines the association between External
@@ -417,47 +419,7 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
};
#undef X
-/*
- * GCMP needs to be detected before any SMP initialisation
- */
-int __init gcmp_probe(unsigned long addr, unsigned long size)
-{
- if ((mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) &&
- (mips_revision_sconid != MIPS_REVISION_SCON_GT64120)) {
- gcmp_present = 0;
- pr_debug("GCMP NOT present\n");
- return gcmp_present;
- }
-
- if (gcmp_present >= 0)
- return gcmp_present;
-
- _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
- _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
- gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
-
- if (gcmp_present)
- pr_debug("GCMP present\n");
- return gcmp_present;
-}
-
-/* Return the number of IOCU's present */
-int __init gcmp_niocu(void)
-{
- return gcmp_present ?
- (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF :
- 0;
-}
-
-/* Set GCMP region attributes */
-void __init gcmp_setregion(int region, unsigned long base,
- unsigned long mask, int type)
-{
- GCMPGCBn(CMxBASE, region) = base;
- GCMPGCBn(CMxMASK, region) = mask | type;
-}
-
-#if defined(CONFIG_MIPS_MT_SMP)
+#ifdef CONFIG_MIPS_GIC_IPI
static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
{
int intr = baseintr + cpu;
@@ -473,7 +435,7 @@ static void __init fill_ipi_map(void)
{
int cpu;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
}
@@ -493,8 +455,8 @@ void __init arch_init_irq(void)
if (!cpu_has_veic)
mips_cpu_irq_init();
- if (gcmp_present) {
- GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
+ if (mips_cm_present()) {
+ write_gcr_gic_base(GIC_BASE_ADDR | CM_GCR_GIC_BASE_GICEN_MSK);
gic_present = 1;
} else {
if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) {
@@ -542,28 +504,9 @@ void __init arch_init_irq(void)
} else if (cpu_has_vint) {
set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch);
-#ifdef CONFIG_MIPS_MT_SMTC
- setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq,
- (0x100 << MIPSCPU_INT_I8259A));
- setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
- &corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
- /*
- * Temporary hack to ensure that the subsidiary device
- * interrupts coing in via the i8259A, but associated
- * with low IRQ numbers, will restore the Status.IM
- * value associated with the i8259A.
- */
- {
- int i;
-
- for (i = 0; i < 16; i++)
- irq_hwmask[i] = (0x100 << MIPSCPU_INT_I8259A);
- }
-#else /* Not SMTC */
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
&corehi_irqaction);
-#endif /* CONFIG_MIPS_MT_SMTC */
} else {
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
@@ -573,33 +516,37 @@ void __init arch_init_irq(void)
if (gic_present) {
/* FIXME */
int i;
-#if defined(CONFIG_MIPS_MT_SMP)
- gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
- gic_resched_int_base = gic_call_int_base - NR_CPUS;
+#if defined(CONFIG_MIPS_GIC_IPI)
+ gic_call_int_base = GIC_NUM_INTRS -
+ (NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids;
+ gic_resched_int_base = gic_call_int_base - nr_cpu_ids;
fill_ipi_map();
#endif
gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
- if (!gcmp_present) {
+ if (!mips_cm_present()) {
/* Enable the GIC */
i = REG(_msc01_biu_base, MSC01_SC_CFG);
REG(_msc01_biu_base, MSC01_SC_CFG) =
(i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
pr_debug("GIC Enabled\n");
}
-#if defined(CONFIG_MIPS_MT_SMP)
+#if defined(CONFIG_MIPS_GIC_IPI)
/* set up ipi interrupts */
if (cpu_has_vint) {
set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch);
}
/* Argh.. this really needs sorting out.. */
- printk("CPU%d: status register was %08x\n", smp_processor_id(), read_c0_status());
+ pr_info("CPU%d: status register was %08x\n",
+ smp_processor_id(), read_c0_status());
write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4);
- printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
+ pr_info("CPU%d: status register now %08x\n",
+ smp_processor_id(), read_c0_status());
write_c0_status(0x1100dc00);
- printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
- for (i = 0; i < NR_CPUS; i++) {
+ pr_info("CPU%d: status register frc %08x\n",
+ smp_processor_id(), read_c0_status());
+ for (i = 0; i < nr_cpu_ids; i++) {
arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
GIC_RESCHED_INT(i), &irq_resched);
arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
@@ -616,11 +563,15 @@ void __init arch_init_irq(void)
cpu_ipi_call_irq = MSC01E_INT_SW1;
} else {
if (cpu_has_vint) {
- set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
- set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
+ set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ,
+ ipi_resched_dispatch);
+ set_vi_handler (MIPS_CPU_IPI_CALL_IRQ,
+ ipi_call_dispatch);
}
- cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
- cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
+ cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE +
+ MIPS_CPU_IPI_RESCHED_IRQ;
+ cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE +
+ MIPS_CPU_IPI_CALL_IRQ;
}
arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
@@ -630,9 +581,7 @@ void __init arch_init_irq(void)
void malta_be_init(void)
{
- if (gcmp_present) {
- /* Could change CM error mask register */
- }
+ /* Could change CM error mask register. */
}
@@ -699,27 +648,27 @@ 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 (gcmp_present) {
- unsigned long cm_error = GCMPGCB(GCMEC);
- unsigned long cm_addr = GCMPGCB(GCMEA);
- unsigned long cm_other = GCMPGCB(GCMEO);
+ 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 & GCMP_GCB_GMEC_ERROR_TYPE_MSK);
+ cause = cm_error & CM_GCR_ERROR_CAUSE_ERRTYPE_MSK;
if (cause != 0) {
- cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF;
+ 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 mcmd_bits = (cm_error >> 7) & 0x1f;
+ unsigned long cmd_bits = (cm_error >> 7) & 0x1f;
unsigned long stag_bits = (cm_error >> 3) & 15;
unsigned long sport_bits = (cm_error >> 0) & 7;
snprintf(buf, sizeof(buf),
"CCA=%lu TR=%s MCmd=%s STag=%lu "
"SPort=%lu\n",
- cca_bits, tr[tr_bits], mcmd[mcmd_bits],
+ cca_bits, tr[tr_bits], mcmd[cmd_bits],
stag_bits, sport_bits);
} else {
/* glob state & sresp together */
@@ -728,7 +677,7 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
unsigned long c1_bits = (cm_error >> 12) & 7;
unsigned long c0_bits = (cm_error >> 9) & 7;
unsigned long sc_bit = (cm_error >> 8) & 1;
- unsigned long mcmd_bits = (cm_error >> 3) & 0x1f;
+ unsigned long cmd_bits = (cm_error >> 3) & 0x1f;
unsigned long sport_bits = (cm_error >> 0) & 7;
snprintf(buf, sizeof(buf),
"C3=%s C2=%s C1=%s C0=%s SC=%s "
@@ -736,19 +685,19 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
core[c3_bits], core[c2_bits],
core[c1_bits], core[c0_bits],
sc_bit ? "True" : "False",
- mcmd[mcmd_bits], sport_bits);
+ mcmd[cmd_bits], sport_bits);
}
- ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >>
- GCMP_GCB_GMEO_ERROR_2ND_SHF;
+ ocause = (cm_other & CM_GCR_ERROR_MULT_ERR2ND_MSK) >>
+ CM_GCR_ERROR_MULT_ERR2ND_SHF;
- printk("CM_ERROR=%08lx %s <%s>\n", cm_error,
+ pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error,
causes[cause], buf);
- printk("CM_ADDR =%08lx\n", cm_addr);
- printk("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
+ pr_err("CM_ADDR =%08lx\n", cm_addr);
+ pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
/* reprime cause register */
- GCMPGCB(GCMEC) = 0;
+ write_gcr_error_cause(0);
}
}
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index 1f73d63e92a..6d977309675 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -24,22 +24,30 @@ 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(void)
+fw_memblock_t * __init fw_getmdesc(int eva)
{
- char *memsize_str, *ptr;
- unsigned int memsize;
+ char *memsize_str, *ememsize_str = NULL, *ptr;
+ unsigned long memsize = 0, ememsize = 0;
static char cmdline[COMMAND_LINE_SIZE] __initdata;
- long val;
int tmp;
/* otherwise look in the environment */
+
memsize_str = fw_getenv("memsize");
- if (!memsize_str) {
+ if (memsize_str)
+ tmp = kstrtol(memsize_str, 0, &memsize);
+ if (eva) {
+ /* Look for ememsize for EVA */
+ ememsize_str = fw_getenv("ememsize");
+ if (ememsize_str)
+ tmp = kstrtol(ememsize_str, 0, &ememsize);
+ }
+ if (!memsize && !ememsize) {
pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
physical_memsize = 0x02000000;
} else {
- tmp = kstrtol(memsize_str, 0, &val);
- physical_memsize = (unsigned long)val;
+ /* If ememsize is set, then set physical_memsize to that */
+ physical_memsize = ememsize ? : memsize;
}
#ifdef CONFIG_CPU_BIG_ENDIAN
@@ -54,20 +62,30 @@ fw_memblock_t * __init fw_getmdesc(void)
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, &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 = 0x00000000;
+ mdesc[0].base = PHYS_OFFSET;
mdesc[0].size = 0x00001000;
mdesc[1].type = fw_code;
- mdesc[1].base = 0x00001000;
+ mdesc[1].base = mdesc[0].base + 0x00001000UL;
mdesc[1].size = 0x000ef000;
/*
@@ -78,21 +96,27 @@ fw_memblock_t * __init fw_getmdesc(void)
* devices.
*/
mdesc[2].type = fw_dontuse;
- mdesc[2].base = 0x000f0000;
+ mdesc[2].base = mdesc[0].base + 0x000f0000UL;
mdesc[2].size = 0x00010000;
mdesc[3].type = fw_dontuse;
- mdesc[3].base = 0x00100000;
+ mdesc[3].base = mdesc[0].base + 0x00100000UL;
mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
- mdesc[3].base;
+ 0x00100000UL;
mdesc[4].type = fw_free;
- mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
- mdesc[4].size = memsize - mdesc[4].base;
+ 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) {
@@ -109,7 +133,9 @@ void __init fw_meminit(void)
{
fw_memblock_t *p;
- p = fw_getmdesc();
+ 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;
diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c
index 132f8663825..e1dd1c1d3fd 100644
--- a/arch/mips/mti-malta/malta-platform.c
+++ b/arch/mips/mti-malta/malta-platform.c
@@ -47,6 +47,7 @@
static struct plat_serial8250_port uart8250_data[] = {
SMC_PORT(0x3F8, 4),
SMC_PORT(0x2F8, 3),
+#ifndef CONFIG_MIPS_CMP
{
.mapbase = 0x1f000900, /* The CBUS UART */
.irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
@@ -55,6 +56,7 @@ static struct plat_serial8250_port uart8250_data[] = {
.flags = CBUS_UART_FLAGS,
.regshift = 3,
},
+#endif
{ },
};
diff --git a/arch/mips/mti-malta/malta-pm.c b/arch/mips/mti-malta/malta-pm.c
new file mode 100644
index 00000000000..c1e456c01a4
--- /dev/null
+++ b/arch/mips/mti-malta/malta-pm.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+
+#include <asm/mach-malta/malta-pm.h>
+
+static struct pci_bus *pm_pci_bus;
+static resource_size_t pm_io_offset;
+
+int mips_pm_suspend(unsigned state)
+{
+ int spec_devid;
+ u16 sts;
+
+ if (!pm_pci_bus || !pm_io_offset)
+ return -ENODEV;
+
+ /* Ensure the power button status is clear */
+ while (1) {
+ sts = inw(pm_io_offset + PIIX4_FUNC3IO_PMSTS);
+ if (!(sts & PIIX4_FUNC3IO_PMSTS_PWRBTN_STS))
+ break;
+ outw(sts, pm_io_offset + PIIX4_FUNC3IO_PMSTS);
+ }
+
+ /* Enable entry to suspend */
+ outw(state | PIIX4_FUNC3IO_PMCNTRL_SUS_EN,
+ pm_io_offset + PIIX4_FUNC3IO_PMCNTRL);
+
+ /* If the special cycle occurs too soon this doesn't work... */
+ mdelay(10);
+
+ /*
+ * The PIIX4 will enter the suspend state only after seeing a special
+ * cycle with the correct magic data on the PCI bus. Generate that
+ * cycle now.
+ */
+ spec_devid = PCI_DEVID(0, PCI_DEVFN(0x1f, 0x7));
+ pci_bus_write_config_dword(pm_pci_bus, spec_devid, 0,
+ PIIX4_SUSPEND_MAGIC);
+
+ /* Give the system some time to power down */
+ mdelay(1000);
+
+ return 0;
+}
+
+static int __init malta_pm_setup(void)
+{
+ struct pci_dev *dev;
+ int res, io_region = PCI_BRIDGE_RESOURCES;
+
+ /* Find a reference to the PCI bus */
+ pm_pci_bus = pci_find_next_bus(NULL);
+ if (!pm_pci_bus) {
+ pr_warn("malta-pm: failed to find reference to PCI bus\n");
+ return -ENODEV;
+ }
+
+ /* Find the PIIX4 PM device */
+ dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID,
+ PCI_ANY_ID, NULL);
+ if (!dev) {
+ pr_warn("malta-pm: failed to find PIIX4 PM\n");
+ return -ENODEV;
+ }
+
+ /* Request access to the PIIX4 PM IO registers */
+ res = pci_request_region(dev, io_region, "PIIX4 PM IO registers");
+ if (res) {
+ pr_warn("malta-pm: failed to request PM IO registers (%d)\n",
+ res);
+ pci_dev_put(dev);
+ return -ENODEV;
+ }
+
+ /* Find the offset to the PIIX4 PM IO registers */
+ pm_io_offset = pci_resource_start(dev, io_region);
+
+ pci_dev_put(dev);
+ return 0;
+}
+
+late_initcall(malta_pm_setup);
diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c
index d627d4b2b47..2fd2cc2c503 100644
--- a/arch/mips/mti-malta/malta-reset.c
+++ b/arch/mips/mti-malta/malta-reset.c
@@ -10,6 +10,7 @@
#include <linux/pm.h>
#include <asm/reboot.h>
+#include <asm/mach-malta/malta-pm.h>
#define SOFTRES_REG 0x1f000500
#define GORESET 0x42
@@ -24,17 +25,22 @@ static void mips_machine_restart(char *command)
static void mips_machine_halt(void)
{
- unsigned int __iomem *softres_reg =
- ioremap(SOFTRES_REG, sizeof(unsigned int));
+ while (true);
+}
- __raw_writel(GORESET, softres_reg);
+static void mips_machine_power_off(void)
+{
+ mips_pm_suspend(PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF);
+
+ pr_info("Failed to power down, resetting\n");
+ mips_machine_restart(NULL);
}
static int __init mips_reboot_setup(void)
{
_machine_restart = mips_machine_restart;
_machine_halt = mips_machine_halt;
- pm_power_off = mips_machine_halt;
+ pm_power_off = mips_machine_power_off;
return 0;
}
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
index c72a0693678..db7c9e5826a 100644
--- a/arch/mips/mti-malta/malta-setup.c
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -26,12 +26,12 @@
#include <linux/time.h>
#include <asm/fw/fw.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/traps.h>
-#include <asm/gcmpregs.h>
#ifdef CONFIG_VT
#include <linux/console.h>
#endif
@@ -77,11 +77,7 @@ const char *get_system_type(void)
return "MIPS Malta";
}
-#if defined(CONFIG_MIPS_MT_SMTC)
-const char display_string[] = " SMTC LINUX ON MALTA ";
-#else
const char display_string[] = " LINUX ON MALTA ";
-#endif /* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_BLK_DEV_FD
static void __init fd_activate(void)
@@ -127,7 +123,7 @@ static int __init plat_enable_iocoherency(void)
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
pr_info("Enabled Bonito IOBC coherency\n");
}
- } else if (gcmp_niocu() != 0) {
+ } else if (mips_cm_numiocu() != 0) {
/* Nothing special needs to be done to enable coherency */
pr_info("CMP IOCU detected\n");
if ((*(unsigned int *)0xbf403000 & 0x81) != 0x81) {
@@ -165,7 +161,6 @@ static void __init plat_setup_iocoherency(void)
#endif
}
-#ifdef CONFIG_BLK_DEV_IDE
static void __init pci_clock_check(void)
{
unsigned int __iomem *jmpr_p =
@@ -175,18 +170,25 @@ static void __init pci_clock_check(void)
33, 20, 25, 30, 12, 16, 37, 10
};
int pciclock = pciclocks[jmpr];
- char *argptr = fw_getcmdline();
+ char *optptr, *argptr = fw_getcmdline();
+
+ /*
+ * If user passed a pci_clock= option, don't tack on another one
+ */
+ optptr = strstr(argptr, "pci_clock=");
+ if (optptr && (optptr == argptr || optptr[-1] == ' '))
+ return;
- if (pciclock != 33 && !strstr(argptr, "idebus=")) {
- pr_warn("WARNING: PCI clock is %dMHz, setting idebus\n",
+ if (pciclock != 33) {
+ pr_warn("WARNING: PCI clock is %dMHz, setting pci_clock\n",
pciclock);
argptr += strlen(argptr);
- sprintf(argptr, " idebus=%d", pciclock);
+ sprintf(argptr, " pci_clock=%d", pciclock);
if (pciclock < 20 || pciclock > 66)
- pr_warn("WARNING: IDE timing calculations will be incorrect\n");
+ pr_warn("WARNING: IDE timing calculations will be "
+ "incorrect\n");
}
}
-#endif
#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
static void __init screen_info_setup(void)
@@ -247,6 +249,10 @@ void __init plat_mem_setup(void)
{
unsigned int i;
+ if (config_enabled(CONFIG_EVA))
+ /* EVA has already been configured in mach-malta/kernel-init.h */
+ pr_info("Enhanced Virtual Addressing (EVA) activated\n");
+
mips_pcibios_init();
/* Request I/O space for devices used on the Malta board. */
@@ -268,9 +274,7 @@ void __init plat_mem_setup(void)
plat_setup_iocoherency();
-#ifdef CONFIG_BLK_DEV_IDE
pci_clock_check();
-#endif
#ifdef CONFIG_BLK_DEV_FD
fd_activate();
diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c
deleted file mode 100644
index c4849904f01..00000000000
--- a/arch/mips/mti-malta/malta-smtc.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Malta Platform-specific hooks for SMP operation
- */
-#include <linux/irq.h>
-#include <linux/init.h>
-
-#include <asm/mipsregs.h>
-#include <asm/mipsmtregs.h>
-#include <asm/smtc.h>
-#include <asm/smtc_ipi.h>
-
-/* VPE/SMP Prototype implements platform interfaces directly */
-
-/*
- * Cause the specified action to be performed on a targeted "CPU"
- */
-
-static void msmtc_send_ipi_single(int cpu, unsigned int action)
-{
- /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
- smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
-}
-
-static void msmtc_send_ipi_mask(const struct cpumask *mask, unsigned int action)
-{
- unsigned int i;
-
- for_each_cpu(i, mask)
- msmtc_send_ipi_single(i, action);
-}
-
-/*
- * Post-config but pre-boot cleanup entry point
- */
-static void msmtc_init_secondary(void)
-{
- int myvpe;
-
- /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
- myvpe = read_c0_tcbind() & TCBIND_CURVPE;
- if (myvpe != 0) {
- /* Ideally, this should be done only once per VPE, but... */
- clear_c0_status(ST0_IM);
- set_c0_status((0x100 << cp0_compare_irq)
- | (0x100 << MIPS_CPU_IPI_IRQ));
- if (cp0_perfcount_irq >= 0)
- set_c0_status(0x100 << cp0_perfcount_irq);
- }
-
- smtc_init_secondary();
-}
-
-/*
- * Platform "CPU" startup hook
- */
-static void msmtc_boot_secondary(int cpu, struct task_struct *idle)
-{
- smtc_boot_secondary(cpu, idle);
-}
-
-/*
- * SMP initialization finalization entry point
- */
-static void msmtc_smp_finish(void)
-{
- smtc_smp_finish();
-}
-
-/*
- * Hook for after all CPUs are online
- */
-
-static void msmtc_cpus_done(void)
-{
-}
-
-/*
- * Platform SMP pre-initialization
- *
- * As noted above, we can assume a single CPU for now
- * but it may be multithreaded.
- */
-
-static void __init msmtc_smp_setup(void)
-{
- /*
- * we won't get the definitive value until
- * we've run smtc_prepare_cpus later, but
- * we would appear to need an upper bound now.
- */
- smp_num_siblings = smtc_build_cpu_map(0);
-}
-
-static void __init msmtc_prepare_cpus(unsigned int max_cpus)
-{
- smtc_prepare_cpus(max_cpus);
-}
-
-struct plat_smp_ops msmtc_smp_ops = {
- .send_ipi_single = msmtc_send_ipi_single,
- .send_ipi_mask = msmtc_send_ipi_mask,
- .init_secondary = msmtc_init_secondary,
- .smp_finish = msmtc_smp_finish,
- .cpus_done = msmtc_cpus_done,
- .boot_secondary = msmtc_boot_secondary,
- .smp_setup = msmtc_smp_setup,
- .prepare_cpus = msmtc_prepare_cpus,
-};
-
-#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-/*
- * IRQ affinity hook
- */
-
-
-int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
- bool force)
-{
- cpumask_t tmask;
- int cpu = 0;
- void smtc_set_irq_affinity(unsigned int irq, cpumask_t aff);
-
- /*
- * On the legacy Malta development board, all I/O interrupts
- * are routed through the 8259 and combined in a single signal
- * to the CPU daughterboard, and on the CoreFPGA2/3 34K models,
- * that signal is brought to IP2 of both VPEs. To avoid racing
- * concurrent interrupt service events, IP2 is enabled only on
- * one VPE, by convention VPE0. So long as no bits are ever
- * cleared in the affinity mask, there will never be any
- * interrupt forwarding. But as soon as a program or operator
- * sets affinity for one of the related IRQs, we need to make
- * sure that we don't ever try to forward across the VPE boundary,
- * at least not until we engineer a system where the interrupt
- * _ack() or _end() function can somehow know that it corresponds
- * to an interrupt taken on another VPE, and perform the appropriate
- * restoration of Status.IM state using MFTR/MTTR instead of the
- * normal local behavior. We also ensure that no attempt will
- * be made to forward to an offline "CPU".
- */
-
- cpumask_copy(&tmask, affinity);
- for_each_cpu(cpu, affinity) {
- if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu))
- cpu_clear(cpu, tmask);
- }
- cpumask_copy(d->affinity, &tmask);
-
- if (cpus_empty(tmask))
- /*
- * We could restore a default mask here, but the
- * runtime code can anyway deal with the null set
- */
- printk(KERN_WARNING
- "IRQ affinity leaves no legal CPU for IRQ %d\n", d->irq);
-
- /* Do any generic SMTC IRQ affinity setup */
- smtc_set_irq_affinity(d->irq, tmask);
-
- return IRQ_SET_MASK_OK_NOCOPY;
-}
-#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index 53aad4a3537..3778a359f3a 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -27,6 +27,7 @@
#include <linux/timex.h>
#include <linux/mc146818rtc.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/hardirq.h>
@@ -41,8 +42,6 @@
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/maltaint.h>
-unsigned long cpu_khz;
-
static int mips_cpu_timer_irq;
static int mips_cpu_perf_irq;
extern int cp0_perfcount_irq;
@@ -75,18 +74,8 @@ static void __init estimate_frequencies(void)
unsigned int giccount = 0, gicstart = 0;
#endif
-#if defined (CONFIG_KVM_GUEST) && defined (CONFIG_KVM_HOST_FREQ)
- unsigned int prid = read_c0_prid() & 0xffff00;
-
- /*
- * XXXKYMA: hardwire the CPU frequency to Host Freq/4
- */
- count = (CONFIG_KVM_HOST_FREQ * 1000000) >> 3;
- if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
- (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
- count *= 2;
-
- mips_hpt_frequency = count;
+#if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ
+ mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000;
return;
#endif
@@ -167,11 +156,24 @@ unsigned int get_c0_compare_int(void)
return mips_cpu_timer_irq;
}
+static void __init init_rtc(void)
+{
+ /* stop the clock whilst setting it up */
+ CMOS_WRITE(RTC_SET | RTC_24H, RTC_CONTROL);
+
+ /* 32KHz time base */
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
+
+ /* start the clock */
+ CMOS_WRITE(RTC_24H, RTC_CONTROL);
+}
+
void __init plat_time_init(void)
{
- unsigned int prid = read_c0_prid() & 0xffff00;
+ unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
unsigned int freq;
+ init_rtc();
estimate_frequencies();
freq = mips_hpt_frequency;
@@ -181,7 +183,6 @@ void __init plat_time_init(void)
freq = freqround(freq, 5000);
printk("CPU frequency %d.%02d MHz\n", freq/1000000,
(freq%1000000)*100/1000000);
- cpu_khz = freq / 1000;
mips_scroll_message();
diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile
index be114209217..071786fa234 100644
--- a/arch/mips/mti-sead3/Makefile
+++ b/arch/mips/mti-sead3/Makefile
@@ -21,5 +21,7 @@ obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o
obj-$(CONFIG_OF) += sead3.dtb.o
+CFLAGS_sead3-setup.o = -I$(src)/../../../scripts/dtc/libfdt
+
$(obj)/%.dtb: $(obj)/%.dts
$(call if_changed,dtc)
diff --git a/arch/mips/mti-sead3/sead3-mtd.c b/arch/mips/mti-sead3/sead3-mtd.c
index ffa35f50978..f9c890d7267 100644
--- a/arch/mips/mti-sead3/sead3-mtd.c
+++ b/arch/mips/mti-sead3/sead3-mtd.c
@@ -50,5 +50,4 @@ static int __init sead3_mtd_init(void)
return 0;
}
-
-module_init(sead3_mtd_init)
+device_initcall(sead3_mtd_init);
diff --git a/arch/mips/mti-sead3/sead3-pic32-bus.c b/arch/mips/mti-sead3/sead3-pic32-bus.c
index eb2bf936d10..3b12aa5a7c8 100644
--- a/arch/mips/mti-sead3/sead3-pic32-bus.c
+++ b/arch/mips/mti-sead3/sead3-pic32-bus.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
-#include <linux/init.h>
#include <linux/io.h>
#include <linux/errno.h>
diff --git a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
index b921e5ec507..80fe194cfa5 100644
--- a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
+++ b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
@@ -312,16 +312,13 @@ static int i2c_platform_probe(struct platform_device *pdev)
pr_debug("i2c_platform_probe\n");
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- ret = -ENODEV;
- goto out;
- }
+ if (!r)
+ return -ENODEV;
- priv = kzalloc(sizeof(struct i2c_platform_data), GFP_KERNEL);
- if (!priv) {
- ret = -ENOMEM;
- goto out;
- }
+ priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_platform_data),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
/* FIXME: need to allocate resource in PIC32 space */
#if 0
@@ -330,10 +327,8 @@ static int i2c_platform_probe(struct platform_device *pdev)
#else
priv->base = r->start;
#endif
- if (!priv->base) {
- ret = -EBUSY;
- goto out_mem;
- }
+ if (!priv->base)
+ return -EBUSY;
priv->xfer_timeout = 200;
priv->ack_timeout = 200;
@@ -348,17 +343,13 @@ static int i2c_platform_probe(struct platform_device *pdev)
i2c_platform_setup(priv);
ret = i2c_add_numbered_adapter(&priv->adap);
- if (ret == 0) {
- platform_set_drvdata(pdev, priv);
- return 0;
+ if (ret) {
+ i2c_platform_disable(priv);
+ return ret;
}
- i2c_platform_disable(priv);
-
-out_mem:
- kfree(priv);
-out:
- return ret;
+ platform_set_drvdata(pdev, priv);
+ return 0;
}
static int i2c_platform_remove(struct platform_device *pdev)
@@ -369,7 +360,6 @@ static int i2c_platform_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
i2c_del_adapter(&priv->adap);
i2c_platform_disable(priv);
- kfree(priv);
return 0;
}
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
index b5059dc899f..e43f4801a24 100644
--- a/arch/mips/mti-sead3/sead3-setup.c
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -4,11 +4,15 @@
* for more details.
*
* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
*/
#include <linux/init.h>
+#include <linux/libfdt.h>
#include <linux/of_platform.h>
#include <linux/of_fdt.h>
-#include <linux/bootmem.h>
+
+#include <asm/prom.h>
+#include <asm/fw/fw.h>
#include <asm/mips-boards/generic.h>
@@ -17,27 +21,91 @@ const char *get_system_type(void)
return "MIPS SEAD3";
}
+static uint32_t get_memsize_from_cmdline(void)
+{
+ int memsize = 0;
+ char *p = arcs_cmdline;
+ char *s = "memsize=";
+
+ p = strstr(p, s);
+ if (p) {
+ p += strlen(s);
+ memsize = memparse(p, NULL);
+ }
+
+ return memsize;
+}
+
+static uint32_t get_memsize_from_env(void)
+{
+ int memsize = 0;
+ char *p;
+
+ p = fw_getenv("memsize");
+ if (p)
+ memsize = memparse(p, NULL);
+
+ return memsize;
+}
+
+static uint32_t get_memsize(void)
+{
+ uint32_t memsize;
+
+ memsize = get_memsize_from_cmdline();
+ if (memsize)
+ return memsize;
+
+ return get_memsize_from_env();
+}
+
+static void __init parse_memsize_param(void)
+{
+ int offset;
+ const uint64_t *prop_value;
+ int prop_len;
+ uint32_t memsize = get_memsize();
+
+ if (!memsize)
+ return;
+
+ offset = fdt_path_offset(__dtb_start, "/memory");
+ if (offset > 0) {
+ uint64_t new_value;
+ /*
+ * reg contains 2 32-bits BE values, offset and size. We just
+ * want to replace the size value without affecting the offset
+ */
+ prop_value = fdt_getprop(__dtb_start, offset, "reg", &prop_len);
+ new_value = be64_to_cpu(*prop_value);
+ new_value = (new_value & ~0xffffffffllu) | memsize;
+ fdt_setprop_inplace_u64(__dtb_start, offset, "reg", new_value);
+ }
+}
+
void __init plat_mem_setup(void)
{
+ /* allow command line/bootloader env to override memory size in DT */
+ parse_memsize_param();
+
/*
* Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing
*/
- __dt_setup_arch(&__dtb_start);
+ __dt_setup_arch(__dtb_start);
}
void __init device_tree_init(void)
{
- unsigned long base, size;
-
if (!initial_boot_params)
return;
- base = virt_to_phys((void *)initial_boot_params);
- size = be32_to_cpu(initial_boot_params->totalsize);
-
- /* Before we do anything, lets reserve the dt blob */
- reserve_bootmem(base, size, BOOTMEM_DEFAULT);
+ unflatten_and_copy_device_tree();
+}
- unflatten_device_tree();
+static int __init customize_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ return 0;
}
+arch_initcall(customize_machine);
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c
index a43ea3cc0a3..678d03d53c6 100644
--- a/arch/mips/mti-sead3/sead3-time.c
+++ b/arch/mips/mti-sead3/sead3-time.c
@@ -7,13 +7,12 @@
*/
#include <linux/init.h>
+#include <asm/cpu.h>
#include <asm/setup.h>
#include <asm/time.h>
#include <asm/irq.h>
#include <asm/mips-boards/generic.h>
-unsigned long cpu_khz;
-
static int mips_cpu_timer_irq;
static int mips_cpu_perf_irq;
@@ -34,7 +33,7 @@ static void __iomem *status_reg = (void __iomem *)0xbf000410;
*/
static unsigned int __init estimate_cpu_frequency(void)
{
- unsigned int prid = read_c0_prid() & 0xffff00;
+ unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
unsigned int tick = 0;
unsigned int freq;
unsigned int orig;
@@ -108,8 +107,6 @@ void __init plat_time_init(void)
pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000),
(est_freq % 1000000) * 100 / 1000000);
- cpu_khz = est_freq / 1000;
-
mips_scroll_message();
plat_perf_setup();
diff --git a/arch/mips/mti-sead3/sead3.dts b/arch/mips/mti-sead3/sead3.dts
index 658f4378705..e4b317d414f 100644
--- a/arch/mips/mti-sead3/sead3.dts
+++ b/arch/mips/mti-sead3/sead3.dts
@@ -15,10 +15,6 @@
};
};
- chosen {
- bootargs = "console=ttyS1,38400 rootdelay=10 root=/dev/sda3";
- };
-
memory {
device_type = "memory";
reg = <0x0 0x08000000>;
diff --git a/arch/mips/net/Makefile b/arch/mips/net/Makefile
new file mode 100644
index 00000000000..ae74b3a91f5
--- /dev/null
+++ b/arch/mips/net/Makefile
@@ -0,0 +1,3 @@
+# MIPS networking code
+
+obj-$(CONFIG_BPF_JIT) += bpf_jit.o
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
new file mode 100644
index 00000000000..b87390a56a2
--- /dev/null
+++ b/arch/mips/net/bpf_jit.c
@@ -0,0 +1,1431 @@
+/*
+ * Just-In-Time compiler for BPF filters on MIPS
+ *
+ * Copyright (c) 2014 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 <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/filter.h>
+#include <linux/if_vlan.h>
+#include <linux/kconfig.h>
+#include <linux/moduleloader.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <asm/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/cpu-features.h>
+#include <asm/uasm.h>
+
+#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
+ *
+ * On entry (*bpf_func)(*skb, *filter)
+ * a0 = MIPS_R_A0 = skb;
+ * a1 = MIPS_R_A1 = filter;
+ *
+ * Stack
+ * ...
+ * M[15]
+ * M[14]
+ * M[13]
+ * ...
+ * M[0] <-- r_M
+ * saved reg k-1
+ * saved reg k-2
+ * ...
+ * saved reg 0 <-- r_sp
+ * <no argument area>
+ *
+ * Packet layout
+ *
+ * <--------------------- len ------------------------>
+ * <--skb-len(r_skb_hl)-->< ----- skb->data_len ------>
+ * ----------------------------------------------------
+ * | skb->data |
+ * ----------------------------------------------------
+ */
+
+#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 */
+#define SEEN_CALL (1 << BPF_MEMWORDS)
+#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)
+
+/* Arguments used by JIT */
+#define ARGS_USED_BY_JIT 2 /* only applicable to 64-bit */
+
+#define SBIT(x) (1 << (x)) /* Signed version of BIT() */
+
+/**
+ * struct jit_ctx - JIT context
+ * @skf: The sk_filter
+ * @prologue_bytes: Number of bytes for prologue
+ * @idx: Instruction index
+ * @flags: JIT flags
+ * @offsets: Instruction offsets
+ * @target: Memory location for the compiled filter
+ */
+struct jit_ctx {
+ const struct sk_filter *skf;
+ unsigned int prologue_bytes;
+ u32 idx;
+ u32 flags;
+ u32 *offsets;
+ u32 *target;
+};
+
+
+static inline int optimize_div(u32 *k)
+{
+ /* power of 2 divides can be implemented with right shift */
+ if (!(*k & (*k-1))) {
+ *k = ilog2(*k);
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline void emit_jit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx);
+
+/* Simply emit the instruction if the JIT memory space has been allocated */
+#define emit_instr(ctx, func, ...) \
+do { \
+ if ((ctx)->target != NULL) { \
+ u32 *p = &(ctx)->target[ctx->idx]; \
+ uasm_i_##func(&p, ##__VA_ARGS__); \
+ } \
+ (ctx)->idx++; \
+} while (0)
+
+/* Determine if immediate is within the 16-bit signed range */
+static inline bool is_range16(s32 imm)
+{
+ return !(imm >= SBIT(15) || imm < -SBIT(15));
+}
+
+static inline void emit_addu(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, addu, dst, src1, src2);
+}
+
+static inline void emit_nop(struct jit_ctx *ctx)
+{
+ emit_instr(ctx, nop);
+}
+
+/* Load a u32 immediate to a register */
+static inline void emit_load_imm(unsigned int dst, u32 imm, struct jit_ctx *ctx)
+{
+ if (ctx->target != NULL) {
+ /* addiu can only handle s16 */
+ if (!is_range16(imm)) {
+ u32 *p = &ctx->target[ctx->idx];
+ uasm_i_lui(&p, r_tmp_imm, (s32)imm >> 16);
+ p = &ctx->target[ctx->idx + 1];
+ uasm_i_ori(&p, dst, r_tmp_imm, imm & 0xffff);
+ } else {
+ u32 *p = &ctx->target[ctx->idx];
+ uasm_i_addiu(&p, dst, r_zero, imm);
+ }
+ }
+ ctx->idx++;
+
+ if (!is_range16(imm))
+ ctx->idx++;
+}
+
+static inline void emit_or(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, or, dst, src1, src2);
+}
+
+static inline void emit_ori(unsigned int dst, unsigned src, u32 imm,
+ struct jit_ctx *ctx)
+{
+ if (imm >= BIT(16)) {
+ emit_load_imm(r_tmp, imm, ctx);
+ emit_or(dst, src, r_tmp, ctx);
+ } else {
+ emit_instr(ctx, ori, dst, src, imm);
+ }
+}
+
+
+static inline void emit_daddu(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, daddu, dst, src1, src2);
+}
+
+static inline void emit_daddiu(unsigned int dst, unsigned int src,
+ int imm, struct jit_ctx *ctx)
+{
+ /*
+ * Only used for stack, so the imm is relatively small
+ * and it fits in 15-bits
+ */
+ emit_instr(ctx, daddiu, dst, src, imm);
+}
+
+static inline void emit_addiu(unsigned int dst, unsigned int src,
+ u32 imm, struct jit_ctx *ctx)
+{
+ if (!is_range16(imm)) {
+ emit_load_imm(r_tmp, imm, ctx);
+ emit_addu(dst, r_tmp, src, ctx);
+ } else {
+ emit_instr(ctx, addiu, dst, src, imm);
+ }
+}
+
+static inline void emit_and(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, and, dst, src1, src2);
+}
+
+static inline void emit_andi(unsigned int dst, unsigned int src,
+ u32 imm, struct jit_ctx *ctx)
+{
+ /* If imm does not fit in u16 then load it to register */
+ if (imm >= BIT(16)) {
+ emit_load_imm(r_tmp, imm, ctx);
+ emit_and(dst, src, r_tmp, ctx);
+ } else {
+ emit_instr(ctx, andi, dst, src, imm);
+ }
+}
+
+static inline void emit_xor(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, xor, dst, src1, src2);
+}
+
+static inline void emit_xori(ptr dst, ptr src, u32 imm, struct jit_ctx *ctx)
+{
+ /* If imm does not fit in u16 then load it to register */
+ if (imm >= BIT(16)) {
+ emit_load_imm(r_tmp, imm, ctx);
+ emit_xor(dst, src, r_tmp, ctx);
+ } else {
+ emit_instr(ctx, xori, dst, src, imm);
+ }
+}
+
+static inline void emit_stack_offset(int offset, struct jit_ctx *ctx)
+{
+ if (config_enabled(CONFIG_64BIT))
+ emit_instr(ctx, daddiu, r_sp, r_sp, offset);
+ else
+ emit_instr(ctx, addiu, r_sp, r_sp, offset);
+
+}
+
+static inline void emit_subu(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, subu, dst, src1, src2);
+}
+
+static inline void emit_neg(unsigned int reg, struct jit_ctx *ctx)
+{
+ emit_subu(reg, r_zero, reg, ctx);
+}
+
+static inline void emit_sllv(unsigned int dst, unsigned int src,
+ unsigned int sa, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, sllv, dst, src, sa);
+}
+
+static inline void emit_sll(unsigned int dst, unsigned int src,
+ unsigned int sa, struct jit_ctx *ctx)
+{
+ /* sa is 5-bits long */
+ if (sa >= BIT(5))
+ /* Shifting >= 32 results in zero */
+ emit_jit_reg_move(dst, r_zero, ctx);
+ else
+ emit_instr(ctx, sll, dst, src, sa);
+}
+
+static inline void emit_srlv(unsigned int dst, unsigned int src,
+ unsigned int sa, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, srlv, dst, src, sa);
+}
+
+static inline void emit_srl(unsigned int dst, unsigned int src,
+ unsigned int sa, struct jit_ctx *ctx)
+{
+ /* sa is 5-bits long */
+ if (sa >= BIT(5))
+ /* Shifting >= 32 results in zero */
+ emit_jit_reg_move(dst, r_zero, ctx);
+ else
+ emit_instr(ctx, srl, dst, src, sa);
+}
+
+static inline void emit_slt(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, slt, dst, src1, src2);
+}
+
+static inline void emit_sltu(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, sltu, dst, src1, src2);
+}
+
+static inline void emit_sltiu(unsigned dst, unsigned int src,
+ unsigned int imm, struct jit_ctx *ctx)
+{
+ /* 16 bit immediate */
+ if (!is_range16((s32)imm)) {
+ emit_load_imm(r_tmp, imm, ctx);
+ emit_sltu(dst, src, r_tmp, ctx);
+ } else {
+ emit_instr(ctx, sltiu, dst, src, imm);
+ }
+
+}
+
+/* Store register on the stack */
+static inline void emit_store_stack_reg(ptr reg, ptr base,
+ unsigned int offset,
+ struct jit_ctx *ctx)
+{
+ if (config_enabled(CONFIG_64BIT))
+ emit_instr(ctx, sd, reg, offset, base);
+ else
+ emit_instr(ctx, sw, reg, offset, base);
+}
+
+static inline void emit_store(ptr reg, ptr base, unsigned int offset,
+ struct jit_ctx *ctx)
+{
+ emit_instr(ctx, sw, reg, offset, base);
+}
+
+static inline void emit_load_stack_reg(ptr reg, ptr base,
+ unsigned int offset,
+ struct jit_ctx *ctx)
+{
+ if (config_enabled(CONFIG_64BIT))
+ emit_instr(ctx, ld, reg, offset, base);
+ else
+ emit_instr(ctx, lw, reg, offset, base);
+}
+
+static inline void emit_load(unsigned int reg, unsigned int base,
+ unsigned int offset, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, lw, reg, offset, base);
+}
+
+static inline void emit_load_byte(unsigned int reg, unsigned int base,
+ unsigned int offset, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, lb, reg, offset, base);
+}
+
+static inline void emit_half_load(unsigned int reg, unsigned int base,
+ unsigned int offset, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, lh, reg, offset, base);
+}
+
+static inline void emit_mul(unsigned int dst, unsigned int src1,
+ unsigned int src2, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, mul, dst, src1, src2);
+}
+
+static inline void emit_div(unsigned int dst, unsigned int src,
+ struct jit_ctx *ctx)
+{
+ if (ctx->target != NULL) {
+ u32 *p = &ctx->target[ctx->idx];
+ uasm_i_divu(&p, dst, src);
+ p = &ctx->target[ctx->idx + 1];
+ uasm_i_mflo(&p, dst);
+ }
+ ctx->idx += 2; /* 2 insts */
+}
+
+static inline void emit_mod(unsigned int dst, unsigned int src,
+ struct jit_ctx *ctx)
+{
+ if (ctx->target != NULL) {
+ u32 *p = &ctx->target[ctx->idx];
+ uasm_i_divu(&p, dst, src);
+ p = &ctx->target[ctx->idx + 1];
+ uasm_i_mflo(&p, dst);
+ }
+ ctx->idx += 2; /* 2 insts */
+}
+
+static inline void emit_dsll(unsigned int dst, unsigned int src,
+ unsigned int sa, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, dsll, dst, src, sa);
+}
+
+static inline void emit_dsrl32(unsigned int dst, unsigned int src,
+ unsigned int sa, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, dsrl32, dst, src, sa);
+}
+
+static inline void emit_wsbh(unsigned int dst, unsigned int src,
+ struct jit_ctx *ctx)
+{
+ emit_instr(ctx, wsbh, dst, src);
+}
+
+/* load pointer to register */
+static inline void emit_load_ptr(unsigned int dst, unsigned int src,
+ int imm, struct jit_ctx *ctx)
+{
+ /* src contains the base addr of the 32/64-pointer */
+ if (config_enabled(CONFIG_64BIT))
+ emit_instr(ctx, ld, dst, imm, src);
+ else
+ emit_instr(ctx, lw, dst, imm, src);
+}
+
+/* load a function pointer to register */
+static inline void emit_load_func(unsigned int reg, ptr imm,
+ struct jit_ctx *ctx)
+{
+ if (config_enabled(CONFIG_64BIT)) {
+ /* At this point imm is always 64-bit */
+ emit_load_imm(r_tmp, (u64)imm >> 32, ctx);
+ emit_dsll(r_tmp_imm, r_tmp, 16, ctx); /* left shift by 16 */
+ emit_ori(r_tmp, r_tmp_imm, (imm >> 16) & 0xffff, ctx);
+ emit_dsll(r_tmp_imm, r_tmp, 16, ctx); /* left shift by 16 */
+ emit_ori(reg, r_tmp_imm, imm & 0xffff, ctx);
+ } else {
+ emit_load_imm(reg, imm, ctx);
+ }
+}
+
+/* Move to real MIPS register */
+static inline void emit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx)
+{
+ if (config_enabled(CONFIG_64BIT))
+ emit_daddu(dst, src, r_zero, ctx);
+ else
+ emit_addu(dst, src, r_zero, ctx);
+}
+
+/* Move to JIT (32-bit) register */
+static inline void emit_jit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx)
+{
+ emit_addu(dst, src, r_zero, ctx);
+}
+
+/* Compute the immediate value for PC-relative branches. */
+static inline u32 b_imm(unsigned int tgt, struct jit_ctx *ctx)
+{
+ if (ctx->target == NULL)
+ return 0;
+
+ /*
+ * We want a pc-relative branch. We only do forward branches
+ * so tgt is always after pc. tgt is the instruction offset
+ * we want to jump to.
+
+ * Branch on MIPS:
+ * I: target_offset <- sign_extend(offset)
+ * I+1: PC += target_offset (delay slot)
+ *
+ * ctx->idx currently points to the branch instruction
+ * but the offset is added to the delay slot so we need
+ * to subtract 4.
+ */
+ return ctx->offsets[tgt] -
+ (ctx->idx * 4 - ctx->prologue_bytes) - 4;
+}
+
+static inline void emit_bcond(int cond, unsigned int reg1, unsigned int reg2,
+ unsigned int imm, struct jit_ctx *ctx)
+{
+ if (ctx->target != NULL) {
+ u32 *p = &ctx->target[ctx->idx];
+
+ switch (cond) {
+ case MIPS_COND_EQ:
+ uasm_i_beq(&p, reg1, reg2, imm);
+ break;
+ case MIPS_COND_NE:
+ uasm_i_bne(&p, reg1, reg2, imm);
+ break;
+ case MIPS_COND_ALL:
+ uasm_i_b(&p, imm);
+ break;
+ default:
+ pr_warn("%s: Unhandled branch conditional: %d\n",
+ __func__, cond);
+ }
+ }
+ ctx->idx++;
+}
+
+static inline void emit_b(unsigned int imm, struct jit_ctx *ctx)
+{
+ emit_bcond(MIPS_COND_ALL, r_zero, r_zero, imm, ctx);
+}
+
+static inline void emit_jalr(unsigned int link, unsigned int reg,
+ struct jit_ctx *ctx)
+{
+ emit_instr(ctx, jalr, link, reg);
+}
+
+static inline void emit_jr(unsigned int reg, struct jit_ctx *ctx)
+{
+ emit_instr(ctx, jr, reg);
+}
+
+static inline u16 align_sp(unsigned int num)
+{
+ /* Double word alignment for 32-bit, quadword for 64-bit */
+ unsigned int align = config_enabled(CONFIG_64BIT) ? 16 : 8;
+ num = (num + (align - 1)) & -align;
+ 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;
+ u32 sflags, tmp_flags;
+
+ /* 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;
+ }
+ i++;
+ tmp_flags >>= 1;
+ }
+
+ /* save return address */
+ if (ctx->flags & SEEN_CALL) {
+ emit_store_stack_reg(r_ra, r_sp, real_off, ctx);
+ real_off += RSIZE;
+ }
+
+ /* Setup r_M leaving the alignment gap if necessary */
+ if (ctx->flags & SEEN_MEM) {
+ if (real_off % (RSIZE * 2))
+ real_off += RSIZE;
+ if (config_enabled(CONFIG_64BIT))
+ emit_daddiu(r_M, r_sp, real_off, ctx);
+ else
+ emit_addiu(r_M, r_sp, real_off, ctx);
+ }
+}
+
+static void restore_bpf_jit_regs(struct jit_ctx *ctx,
+ unsigned int offset)
+{
+ 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;
+ while (tmp_flags) {
+ if ((sflags >> i) & 0x1) {
+ emit_load_stack_reg(MIPS_R_S0 + i, r_sp, real_off,
+ ctx);
+ real_off += RSIZE;
+ }
+ i++;
+ tmp_flags >>= 1;
+ }
+
+ /* restore return address */
+ if (ctx->flags & SEEN_CALL)
+ emit_load_stack_reg(r_ra, r_sp, real_off, ctx);
+
+ /* Restore the sp and discard the scrach memory */
+ emit_stack_offset(align_sp(offset), ctx);
+}
+
+static unsigned int get_stack_depth(struct jit_ctx *ctx)
+{
+ int sp_off = 0;
+
+
+ /* How may s* regs do we need to preserved? */
+ sp_off += hweight32(ctx->flags >> SEEN_SREG_SFT) * RSIZE;
+
+ 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;
+
+ /*
+ * Subtract the bytes for the last registers since we only care about
+ * the location on the stack pointer.
+ */
+ return sp_off - RSIZE;
+}
+
+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 */
+ sp_off = get_stack_depth(ctx);
+ save_bpf_jit_regs(ctx, sp_off);
+
+ if (ctx->flags & SEEN_SKB)
+ emit_reg_move(r_skb, MIPS_R_A0, 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)))
+ emit_jit_reg_move(r_A, r_zero, ctx);
+}
+
+static void build_epilogue(struct jit_ctx *ctx)
+{
+ unsigned int sp_off;
+
+ /* Calculate the total offset for the stack pointer */
+
+ sp_off = get_stack_depth(ctx);
+ restore_bpf_jit_regs(ctx, sp_off);
+
+ /* Return */
+ emit_jr(r_ra, 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);
+}
+
+#ifdef __BIG_ENDIAN_BITFIELD
+#define PKT_TYPE_MAX (7 << 5)
+#else
+#define PKT_TYPE_MAX 7
+#endif
+static int pkt_type_offset(void)
+{
+ struct sk_buff skb_probe = {
+ .pkt_type = ~0,
+ };
+ u8 *ct = (u8 *)&skb_probe;
+ unsigned int off;
+
+ for (off = 0; off < sizeof(struct sk_buff); off++) {
+ if (ct[off] == PKT_TYPE_MAX)
+ return off;
+ }
+ pr_err_once("Please fix pkt_type_offset(), as pkt_type couldn't be found\n");
+ return -1;
+}
+
+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 sk_filter *prog = ctx->skf;
+ const struct sock_filter *inst;
+ unsigned int i, off, load_order, condt;
+ u32 k, b_off __maybe_unused;
+
+ for (i = 0; i < prog->len; i++) {
+ u16 code;
+
+ inst = &(prog->insns[i]);
+ pr_debug("%s: code->0x%02x, jt->0x%x, jf->0x%x, k->0x%x\n",
+ __func__, inst->code, inst->jt, inst->jf, inst->k);
+ k = inst->k;
+ code = bpf_anc_helper(inst);
+
+ if (ctx->target == NULL)
+ ctx->offsets[i] = ctx->idx * 4;
+
+ switch (code) {
+ case BPF_LD | BPF_IMM:
+ /* A <- k ==> li r_A, k */
+ ctx->flags |= SEEN_A;
+ emit_load_imm(r_A, k, ctx);
+ break;
+ case BPF_LD | BPF_W | BPF_LEN:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+ /* A <- len ==> lw r_A, offset(skb) */
+ ctx->flags |= SEEN_SKB | SEEN_A;
+ off = offsetof(struct sk_buff, len);
+ emit_load(r_A, r_skb, off, ctx);
+ break;
+ case BPF_LD | BPF_MEM:
+ /* A <- M[k] ==> lw r_A, offset(M) */
+ ctx->flags |= SEEN_MEM | SEEN_A;
+ emit_load(r_A, r_M, SCRATCH_OFF(k), ctx);
+ break;
+ case BPF_LD | BPF_W | BPF_ABS:
+ /* A <- P[k:4] */
+ load_order = 2;
+ goto load;
+ case BPF_LD | BPF_H | BPF_ABS:
+ /* A <- P[k:2] */
+ load_order = 1;
+ goto load;
+ case BPF_LD | BPF_B | BPF_ABS:
+ /* A <- P[k:1] */
+ load_order = 0;
+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_S0 |
+ SEEN_SKB | SEEN_A;
+
+ emit_load_func(r_s0, (ptr)load_func[load_order],
+ 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);
+ /* Return with error */
+ emit_b(b_imm(prog->len, ctx), ctx);
+ emit_reg_move(r_ret, r_zero, ctx);
+ break;
+ case BPF_LD | BPF_W | BPF_IND:
+ /* A <- P[X + k:4] */
+ load_order = 2;
+ goto load_ind;
+ case BPF_LD | BPF_H | BPF_IND:
+ /* A <- P[X + k:2] */
+ load_order = 1;
+ goto load_ind;
+ case BPF_LD | BPF_B | BPF_IND:
+ /* A <- P[X + k:1] */
+ load_order = 0;
+load_ind:
+ ctx->flags |= SEEN_OFF | SEEN_X;
+ emit_addiu(r_off, r_X, k, ctx);
+ goto load_common;
+ case BPF_LDX | BPF_IMM:
+ /* X <- k */
+ ctx->flags |= SEEN_X;
+ emit_load_imm(r_X, k, ctx);
+ break;
+ case BPF_LDX | BPF_MEM:
+ /* X <- M[k] */
+ ctx->flags |= SEEN_X | SEEN_MEM;
+ emit_load(r_X, r_M, SCRATCH_OFF(k), ctx);
+ break;
+ case BPF_LDX | BPF_W | BPF_LEN:
+ /* X <- len */
+ ctx->flags |= SEEN_X | SEEN_SKB;
+ off = offsetof(struct sk_buff, len);
+ 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;
+ /* Load offset to a1 */
+ emit_load_func(r_s0, (ptr)jit_get_skb_b, ctx);
+ /*
+ * This may emit two instructions so it may not fit
+ * in the delay slot. So use a0 in the delay slot.
+ */
+ emit_load_imm(MIPS_R_A1, k, ctx);
+ 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 */
+ /* We are good */
+ /* X <- P[1:K] & 0xf */
+ emit_andi(r_X, r_val, 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 */
+ ctx->flags |= SEEN_MEM | SEEN_A;
+ emit_store(r_A, r_M, SCRATCH_OFF(k), ctx);
+ break;
+ case BPF_STX:
+ /* M[k] <- X */
+ ctx->flags |= SEEN_MEM | SEEN_X;
+ emit_store(r_X, r_M, SCRATCH_OFF(k), ctx);
+ break;
+ case BPF_ALU | BPF_ADD | BPF_K:
+ /* A += K */
+ ctx->flags |= SEEN_A;
+ emit_addiu(r_A, r_A, k, ctx);
+ break;
+ case BPF_ALU | BPF_ADD | BPF_X:
+ /* A += X */
+ ctx->flags |= SEEN_A | SEEN_X;
+ emit_addu(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_SUB | BPF_K:
+ /* A -= K */
+ ctx->flags |= SEEN_A;
+ emit_addiu(r_A, r_A, -k, ctx);
+ break;
+ case BPF_ALU | BPF_SUB | BPF_X:
+ /* A -= X */
+ ctx->flags |= SEEN_A | SEEN_X;
+ emit_subu(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_MUL | BPF_K:
+ /* A *= K */
+ /* Load K to scratch register before MUL */
+ ctx->flags |= SEEN_A | SEEN_S0;
+ emit_load_imm(r_s0, k, ctx);
+ emit_mul(r_A, r_A, r_s0, ctx);
+ break;
+ case BPF_ALU | BPF_MUL | BPF_X:
+ /* A *= X */
+ ctx->flags |= SEEN_A | SEEN_X;
+ emit_mul(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_DIV | BPF_K:
+ /* A /= k */
+ if (k == 1)
+ break;
+ if (optimize_div(&k)) {
+ ctx->flags |= SEEN_A;
+ emit_srl(r_A, r_A, k, ctx);
+ break;
+ }
+ ctx->flags |= SEEN_A | SEEN_S0;
+ emit_load_imm(r_s0, k, ctx);
+ emit_div(r_A, r_s0, ctx);
+ break;
+ case BPF_ALU | BPF_MOD | BPF_K:
+ /* A %= k */
+ if (k == 1 || optimize_div(&k)) {
+ ctx->flags |= SEEN_A;
+ emit_jit_reg_move(r_A, r_zero, ctx);
+ } else {
+ ctx->flags |= SEEN_A | SEEN_S0;
+ emit_load_imm(r_s0, k, ctx);
+ emit_mod(r_A, r_s0, ctx);
+ }
+ break;
+ case BPF_ALU | BPF_DIV | BPF_X:
+ /* A /= X */
+ ctx->flags |= SEEN_X | SEEN_A;
+ /* 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_div(r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_MOD | BPF_X:
+ /* A %= X */
+ ctx->flags |= SEEN_X | SEEN_A;
+ /* 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_mod(r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_OR | BPF_K:
+ /* A |= K */
+ ctx->flags |= SEEN_A;
+ emit_ori(r_A, r_A, k, ctx);
+ break;
+ case BPF_ALU | BPF_OR | BPF_X:
+ /* A |= X */
+ ctx->flags |= SEEN_A;
+ emit_ori(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_XOR | BPF_K:
+ /* A ^= k */
+ ctx->flags |= SEEN_A;
+ emit_xori(r_A, r_A, k, ctx);
+ break;
+ case BPF_ANC | SKF_AD_ALU_XOR_X:
+ case BPF_ALU | BPF_XOR | BPF_X:
+ /* A ^= X */
+ ctx->flags |= SEEN_A;
+ emit_xor(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_AND | BPF_K:
+ /* A &= K */
+ ctx->flags |= SEEN_A;
+ emit_andi(r_A, r_A, k, ctx);
+ break;
+ case BPF_ALU | BPF_AND | BPF_X:
+ /* A &= X */
+ ctx->flags |= SEEN_A | SEEN_X;
+ emit_and(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_LSH | BPF_K:
+ /* A <<= K */
+ ctx->flags |= SEEN_A;
+ emit_sll(r_A, r_A, k, ctx);
+ break;
+ case BPF_ALU | BPF_LSH | BPF_X:
+ /* A <<= X */
+ ctx->flags |= SEEN_A | SEEN_X;
+ emit_sllv(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_RSH | BPF_K:
+ /* A >>= K */
+ ctx->flags |= SEEN_A;
+ emit_srl(r_A, r_A, k, ctx);
+ break;
+ case BPF_ALU | BPF_RSH | BPF_X:
+ ctx->flags |= SEEN_A | SEEN_X;
+ emit_srlv(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_ALU | BPF_NEG:
+ /* A = -A */
+ ctx->flags |= SEEN_A;
+ emit_neg(r_A, ctx);
+ break;
+ case BPF_JMP | BPF_JA:
+ /* pc += K */
+ emit_b(b_imm(i + k + 1, ctx), ctx);
+ emit_nop(ctx);
+ break;
+ case BPF_JMP | BPF_JEQ | BPF_K:
+ /* pc += ( A == K ) ? pc->jt : pc->jf */
+ condt = MIPS_COND_EQ | MIPS_COND_K;
+ goto jmp_cmp;
+ case BPF_JMP | BPF_JEQ | BPF_X:
+ ctx->flags |= SEEN_X;
+ /* pc += ( A == X ) ? pc->jt : pc->jf */
+ condt = MIPS_COND_EQ | MIPS_COND_X;
+ goto jmp_cmp;
+ case BPF_JMP | BPF_JGE | BPF_K:
+ /* pc += ( A >= K ) ? pc->jt : pc->jf */
+ condt = MIPS_COND_GE | MIPS_COND_K;
+ goto jmp_cmp;
+ case BPF_JMP | BPF_JGE | BPF_X:
+ ctx->flags |= SEEN_X;
+ /* pc += ( A >= X ) ? pc->jt : pc->jf */
+ condt = MIPS_COND_GE | MIPS_COND_X;
+ goto jmp_cmp;
+ case BPF_JMP | BPF_JGT | BPF_K:
+ /* pc += ( A > K ) ? pc->jt : pc->jf */
+ condt = MIPS_COND_GT | MIPS_COND_K;
+ goto jmp_cmp;
+ case BPF_JMP | BPF_JGT | BPF_X:
+ ctx->flags |= SEEN_X;
+ /* pc += ( A > X ) ? pc->jt : pc->jf */
+ condt = MIPS_COND_GT | MIPS_COND_X;
+jmp_cmp:
+ /* Greater or Equal */
+ if ((condt & MIPS_COND_GE) ||
+ (condt & MIPS_COND_GT)) {
+ if (condt & MIPS_COND_K) { /* K */
+ ctx->flags |= SEEN_S0 | SEEN_A;
+ emit_sltiu(r_s0, r_A, k, ctx);
+ } else { /* X */
+ ctx->flags |= SEEN_S0 | SEEN_A |
+ SEEN_X;
+ emit_sltu(r_s0, r_A, r_X, ctx);
+ }
+ /* A < (K|X) ? r_scrach = 1 */
+ b_off = b_imm(i + inst->jf + 1, ctx);
+ emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off,
+ ctx);
+ emit_nop(ctx);
+ /* A > (K|X) ? scratch = 0 */
+ if (condt & MIPS_COND_GT) {
+ /* Checking for equality */
+ ctx->flags |= SEEN_S0 | SEEN_A | SEEN_X;
+ if (condt & MIPS_COND_K)
+ emit_load_imm(r_s0, k, ctx);
+ else
+ emit_jit_reg_move(r_s0, r_X,
+ ctx);
+ b_off = b_imm(i + inst->jf + 1, ctx);
+ emit_bcond(MIPS_COND_EQ, r_A, r_s0,
+ b_off, ctx);
+ emit_nop(ctx);
+ /* Finally, A > K|X */
+ b_off = b_imm(i + inst->jt + 1, ctx);
+ emit_b(b_off, ctx);
+ emit_nop(ctx);
+ } else {
+ /* A >= (K|X) so jump */
+ b_off = b_imm(i + inst->jt + 1, ctx);
+ emit_b(b_off, ctx);
+ emit_nop(ctx);
+ }
+ } else {
+ /* A == K|X */
+ if (condt & MIPS_COND_K) { /* K */
+ ctx->flags |= SEEN_S0 | SEEN_A;
+ emit_load_imm(r_s0, k, ctx);
+ /* jump true */
+ b_off = b_imm(i + inst->jt + 1, ctx);
+ emit_bcond(MIPS_COND_EQ, r_A, r_s0,
+ b_off, ctx);
+ emit_nop(ctx);
+ /* jump false */
+ b_off = b_imm(i + inst->jf + 1,
+ ctx);
+ emit_bcond(MIPS_COND_NE, r_A, r_s0,
+ b_off, ctx);
+ emit_nop(ctx);
+ } else { /* X */
+ /* jump true */
+ ctx->flags |= SEEN_A | SEEN_X;
+ b_off = b_imm(i + inst->jt + 1,
+ ctx);
+ emit_bcond(MIPS_COND_EQ, r_A, r_X,
+ b_off, ctx);
+ emit_nop(ctx);
+ /* jump false */
+ b_off = b_imm(i + inst->jf + 1, ctx);
+ emit_bcond(MIPS_COND_NE, r_A, r_X,
+ b_off, ctx);
+ emit_nop(ctx);
+ }
+ }
+ break;
+ case BPF_JMP | BPF_JSET | BPF_K:
+ ctx->flags |= SEEN_S0 | SEEN_S1 | 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);
+ /* jump true */
+ b_off = b_imm(i + inst->jt + 1, ctx);
+ emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off, ctx);
+ emit_nop(ctx);
+ /* jump false */
+ b_off = b_imm(i + inst->jf + 1, ctx);
+ emit_b(b_off, ctx);
+ emit_nop(ctx);
+ break;
+ case BPF_JMP | BPF_JSET | BPF_X:
+ ctx->flags |= SEEN_S0 | SEEN_X | SEEN_A;
+ /* pc += (A & X) ? pc -> jt : pc -> jf */
+ emit_and(r_s0, r_A, r_X, ctx);
+ /* jump true */
+ b_off = b_imm(i + inst->jt + 1, ctx);
+ emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off, ctx);
+ emit_nop(ctx);
+ /* jump false */
+ b_off = b_imm(i + inst->jf + 1, ctx);
+ emit_b(b_off, ctx);
+ emit_nop(ctx);
+ break;
+ case BPF_RET | BPF_A:
+ ctx->flags |= SEEN_A;
+ if (i != prog->len - 1)
+ /*
+ * If this is not the last instruction
+ * then jump to the epilogue
+ */
+ emit_b(b_imm(prog->len, ctx), ctx);
+ emit_reg_move(r_ret, r_A, ctx); /* delay slot */
+ break;
+ case BPF_RET | BPF_K:
+ /*
+ * It can emit two instructions so it does not fit on
+ * the delay slot.
+ */
+ emit_load_imm(r_ret, k, ctx);
+ if (i != prog->len - 1) {
+ /*
+ * If this is not the last instruction
+ * then jump to the epilogue
+ */
+ emit_b(b_imm(prog->len, ctx), ctx);
+ emit_nop(ctx);
+ }
+ break;
+ case BPF_MISC | BPF_TAX:
+ /* X = A */
+ ctx->flags |= SEEN_X | SEEN_A;
+ emit_jit_reg_move(r_X, r_A, ctx);
+ break;
+ case BPF_MISC | BPF_TXA:
+ /* A = X */
+ ctx->flags |= SEEN_A | SEEN_X;
+ emit_jit_reg_move(r_A, r_X, ctx);
+ break;
+ /* AUX */
+ case BPF_ANC | SKF_AD_PROTOCOL:
+ /* A = ntohs(skb->protocol */
+ ctx->flags |= SEEN_SKB | SEEN_OFF | SEEN_A;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ protocol) != 2);
+ off = offsetof(struct sk_buff, protocol);
+ emit_half_load(r_A, r_skb, off, ctx);
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ /* This needs little endian fixup */
+ if (cpu_has_mips_r2) {
+ /* R2 and later have the wsbh instruction */
+ emit_wsbh(r_A, r_A, ctx);
+ } else {
+ /* Get first byte */
+ emit_andi(r_tmp_imm, r_A, 0xff, ctx);
+ /* Shift it */
+ emit_sll(r_tmp, r_tmp_imm, 8, ctx);
+ /* Get second byte */
+ emit_srl(r_tmp_imm, r_A, 8, ctx);
+ emit_andi(r_tmp_imm, r_tmp_imm, 0xff, ctx);
+ /* Put everyting together in r_A */
+ emit_or(r_A, r_tmp, r_tmp_imm, ctx);
+ }
+#endif
+ break;
+ case BPF_ANC | SKF_AD_CPU:
+ ctx->flags |= SEEN_A | SEEN_OFF;
+ /* A = current_thread_info()->cpu */
+ BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info,
+ cpu) != 4);
+ off = offsetof(struct thread_info, cpu);
+ /* $28/gp points to the thread_info struct */
+ emit_load(r_A, 28, off, ctx);
+ break;
+ case BPF_ANC | SKF_AD_IFINDEX:
+ /* A = skb->dev->ifindex */
+ ctx->flags |= SEEN_SKB | SEEN_A | SEEN_S0;
+ off = offsetof(struct sk_buff, dev);
+ /* Load *dev pointer */
+ emit_load_ptr(r_s0, r_skb, off, ctx);
+ /* error (0) in the delay slot */
+ emit_bcond(MIPS_COND_EQ, r_s0, r_zero,
+ b_imm(prog->len, ctx), ctx);
+ emit_reg_move(r_ret, r_zero, ctx);
+ BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+ ifindex) != 4);
+ off = offsetof(struct net_device, ifindex);
+ emit_load(r_A, r_s0, off, ctx);
+ break;
+ case BPF_ANC | SKF_AD_MARK:
+ ctx->flags |= SEEN_SKB | SEEN_A;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+ off = offsetof(struct sk_buff, mark);
+ emit_load(r_A, r_skb, off, ctx);
+ break;
+ case BPF_ANC | SKF_AD_RXHASH:
+ ctx->flags |= SEEN_SKB | SEEN_A;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
+ off = offsetof(struct sk_buff, hash);
+ emit_load(r_A, r_skb, off, ctx);
+ break;
+ case BPF_ANC | SKF_AD_VLAN_TAG:
+ case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+ ctx->flags |= SEEN_SKB | SEEN_S0 | SEEN_A;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ vlan_tci) != 2);
+ off = offsetof(struct sk_buff, vlan_tci);
+ emit_half_load(r_s0, r_skb, off, ctx);
+ if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) {
+ emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx);
+ } else {
+ emit_andi(r_A, r_s0, VLAN_TAG_PRESENT, ctx);
+ /* return 1 if present */
+ emit_sltu(r_A, r_zero, r_A, ctx);
+ }
+ break;
+ case BPF_ANC | SKF_AD_PKTTYPE:
+ ctx->flags |= SEEN_SKB;
+
+ off = pkt_type_offset();
+
+ if (off < 0)
+ return -1;
+ emit_load_byte(r_tmp, r_skb, off, ctx);
+ /* Keep only the last 3 bits */
+ emit_andi(r_A, r_tmp, PKT_TYPE_MAX, ctx);
+#ifdef __BIG_ENDIAN_BITFIELD
+ /* Get the actual packet type to the lower 3 bits */
+ emit_srl(r_A, r_A, 5, ctx);
+#endif
+ break;
+ case BPF_ANC | SKF_AD_QUEUE:
+ ctx->flags |= SEEN_SKB | SEEN_A;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ queue_mapping) != 2);
+ BUILD_BUG_ON(offsetof(struct sk_buff,
+ queue_mapping) > 0xff);
+ off = offsetof(struct sk_buff, queue_mapping);
+ emit_half_load(r_A, r_skb, off, ctx);
+ break;
+ default:
+ pr_debug("%s: Unhandled opcode: 0x%02x\n", __FILE__,
+ inst->code);
+ return -1;
+ }
+ }
+
+ /* compute offsets only during the first pass */
+ if (ctx->target == NULL)
+ ctx->offsets[i] = ctx->idx * 4;
+
+ return 0;
+}
+
+int bpf_jit_enable __read_mostly;
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+ struct jit_ctx ctx;
+ unsigned int alloc_size, tmp_idx;
+
+ if (!bpf_jit_enable)
+ return;
+
+ memset(&ctx, 0, sizeof(ctx));
+
+ ctx.offsets = kcalloc(fp->len, sizeof(*ctx.offsets), GFP_KERNEL);
+ if (ctx.offsets == NULL)
+ return;
+
+ ctx.skf = fp;
+
+ if (build_body(&ctx))
+ goto out;
+
+ tmp_idx = ctx.idx;
+ build_prologue(&ctx);
+ ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
+ /* just to complete the ctx.idx count */
+ build_epilogue(&ctx);
+
+ alloc_size = 4 * ctx.idx;
+ ctx.target = module_alloc(alloc_size);
+ if (ctx.target == NULL)
+ goto out;
+
+ /* Clean it */
+ memset(ctx.target, 0, alloc_size);
+
+ ctx.idx = 0;
+
+ /* Generate the actual JIT code */
+ build_prologue(&ctx);
+ build_body(&ctx);
+ build_epilogue(&ctx);
+
+ /* Update the icache */
+ flush_icache_range((ptr)ctx.target, (ptr)(ctx.target + ctx.idx));
+
+ if (bpf_jit_enable > 1)
+ /* Dump JIT code */
+ bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
+
+ fp->bpf_func = (void *)ctx.target;
+ fp->jited = 1;
+
+out:
+ kfree(ctx.offsets);
+}
+
+void bpf_jit_free(struct sk_filter *fp)
+{
+ if (fp->jited)
+ module_free(NULL, fp->bpf_func);
+ kfree(fp);
+}
diff --git a/arch/mips/net/bpf_jit.h b/arch/mips/net/bpf_jit.h
new file mode 100644
index 00000000000..3a5751b4335
--- /dev/null
+++ b/arch/mips/net/bpf_jit.h
@@ -0,0 +1,44 @@
+/*
+ * Just-In-Time compiler for BPF filters on MIPS
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#ifndef BPF_JIT_MIPS_OP_H
+#define BPF_JIT_MIPS_OP_H
+
+/* 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_T6 14
+#define MIPS_R_T7 15
+#define MIPS_R_S0 16
+#define MIPS_R_S1 17
+#define MIPS_R_S2 18
+#define MIPS_R_S3 19
+#define MIPS_R_S4 20
+#define MIPS_R_S5 21
+#define MIPS_R_S6 22
+#define MIPS_R_S7 23
+#define MIPS_R_SP 29
+#define MIPS_R_RA 31
+
+/* Conditional codes */
+#define MIPS_COND_EQ 0x1
+#define MIPS_COND_GE (0x1 << 1)
+#define MIPS_COND_GT (0x1 << 2)
+#define MIPS_COND_NE (0x1 << 3)
+#define MIPS_COND_ALL (0x1 << 4)
+/* Conditionals on X register or K immediate */
+#define MIPS_COND_X (0x1 << 5)
+#define MIPS_COND_K (0x1 << 6)
+
+#endif /* BPF_JIT_MIPS_OP_H */
diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig
index 852a4ee0995..4eb683aef7d 100644
--- a/arch/mips/netlogic/Kconfig
+++ b/arch/mips/netlogic/Kconfig
@@ -28,6 +28,15 @@ config DT_XLP_FVP
pointer to the kernel. The corresponding DTS file is at
arch/mips/netlogic/dts/xlp_fvp.dts
+config DT_XLP_GVP
+ bool "Built-in device tree for XLP GVP boards"
+ default y
+ help
+ Add an FDT blob for XLP GVP board into the kernel.
+ This DTB will be used if the firmware does not pass in a DTB
+ pointer to the kernel. The corresponding DTS file is at
+ arch/mips/netlogic/dts/xlp_gvp.dts
+
config NLM_MULTINODE
bool "Support for multi-chip boards"
depends on NLM_XLP_BOARD
diff --git a/arch/mips/netlogic/common/earlycons.c b/arch/mips/netlogic/common/earlycons.c
index 1902fa22d27..769f93032c5 100644
--- a/arch/mips/netlogic/common/earlycons.c
+++ b/arch/mips/netlogic/common/earlycons.c
@@ -37,9 +37,11 @@
#include <asm/mipsregs.h>
#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/common.h>
#if defined(CONFIG_CPU_XLP)
#include <asm/netlogic/xlp-hal/iomap.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/uart.h>
#elif defined(CONFIG_CPU_XLR)
#include <asm/netlogic/xlr/iomap.h>
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index 1c7e3a1b81a..c100b9afa0a 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -180,6 +180,7 @@ static void __init nlm_init_percpu_irqs(void)
#endif
}
+
void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
{
struct nlm_pic_irq *pic_data;
@@ -202,37 +203,39 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
xirq = nlm_irq_to_xirq(node, irq);
pic_data = irq_get_handler_data(xirq);
+ if (WARN_ON(!pic_data))
+ return;
pic_data->extra_ack = xack;
}
static void nlm_init_node_irqs(int node)
{
- int i, irt;
- uint64_t irqmask;
struct nlm_soc_info *nodep;
+ int i, irt;
pr_info("Init IRQ for node %d\n", node);
nodep = nlm_get_node(node);
- irqmask = PERCPU_IRQ_MASK;
+ nodep->irqmask = PERCPU_IRQ_MASK;
for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
irt = nlm_irq_to_irt(i);
- if (irt == -1)
+ if (irt == -1) /* unused irq */
continue;
- nlm_setup_pic_irq(node, i, i, irt);
- /* set interrupts to first cpu in node */
+ nodep->irqmask |= 1ull << i;
+ if (irt == -2) /* not a direct PIC irq */
+ continue;
+
nlm_pic_init_irt(nodep->picbase, irt, i,
- node * NLM_CPUS_PER_NODE, 0);
- irqmask |= (1ull << i);
+ node * nlm_threads_per_node(), 0);
+ nlm_setup_pic_irq(node, i, i, irt);
}
- nodep->irqmask = irqmask;
}
void nlm_smp_irq_init(int hwcpuid)
{
int node, cpu;
- node = hwcpuid / NLM_CPUS_PER_NODE;
- cpu = hwcpuid % NLM_CPUS_PER_NODE;
+ node = nlm_cpuid_to_node(hwcpuid);
+ cpu = hwcpuid % nlm_threads_per_node();
if (cpu == 0 && node != 0)
nlm_init_node_irqs(node);
@@ -256,13 +259,23 @@ asmlinkage void plat_irq_dispatch(void)
return;
}
+#if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP)
+ /* PCI interrupts need a second level dispatch for MSI bits */
+ if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) {
+ nlm_dispatch_msi(node, i);
+ return;
+ }
+ if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) {
+ nlm_dispatch_msix(node, i);
+ return;
+ }
+
+#endif
/* top level irq handling */
do_IRQ(nlm_irq_to_xirq(node, i));
}
#ifdef CONFIG_OF
-static struct irq_domain *xlp_pic_domain;
-
static const struct irq_domain_ops xlp_pic_irq_domain_ops = {
.xlate = irq_domain_xlate_onetwocell,
};
@@ -271,8 +284,9 @@ static int __init xlp_of_pic_init(struct device_node *node,
struct device_node *parent)
{
const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1;
+ struct irq_domain *xlp_pic_domain;
struct resource res;
- int socid, ret;
+ int socid, ret, bus;
/* we need a hack to get the PIC's SoC chip id */
ret = of_address_to_resource(node, 0, &res);
@@ -280,7 +294,34 @@ static int __init xlp_of_pic_init(struct device_node *node,
pr_err("PIC %s: reg property not found!\n", node->name);
return -EINVAL;
}
- socid = (res.start >> 18) & 0x3;
+
+ if (cpu_is_xlp9xx()) {
+ bus = (res.start >> 20) & 0xf;
+ for (socid = 0; socid < NLM_NR_NODES; socid++) {
+ if (!nlm_node_present(socid))
+ continue;
+ if (nlm_get_node(socid)->socbus == bus)
+ break;
+ }
+ if (socid == NLM_NR_NODES) {
+ pr_err("PIC %s: Node mapping for bus %d not found!\n",
+ node->name, bus);
+ return -EINVAL;
+ }
+ } else {
+ socid = (res.start >> 18) & 0x3;
+ if (!nlm_node_present(socid)) {
+ pr_err("PIC %s: node %d does not exist!\n",
+ node->name, socid);
+ return -EINVAL;
+ }
+ }
+
+ if (!nlm_node_present(socid)) {
+ pr_err("PIC %s: node %d does not exist!\n", node->name, socid);
+ return -EINVAL;
+ }
+
xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs,
nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE,
&xlp_pic_irq_domain_ops, NULL);
@@ -288,8 +329,7 @@ static int __init xlp_of_pic_init(struct device_node *node,
pr_err("PIC %s: Creating legacy domain failed!\n", node->name);
return -EINVAL;
}
- pr_info("Node %d: IRQ domain created for PIC@%pa\n", socid,
- &res.start);
+ pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res);
return 0;
}
diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
index adb18288a6c..701c4bcb9e4 100644
--- a/arch/mips/netlogic/common/reset.S
+++ b/arch/mips/netlogic/common/reset.S
@@ -32,10 +32,11 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <linux/init.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
+#include <asm/cpu.h>
+#include <asm/cacheops.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
@@ -50,8 +51,8 @@
#include <asm/netlogic/xlp-hal/cpucontrol.h>
#define CP0_EBASE $15
-#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
- XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \
+#define SYS_CPU_COHERENT_BASE CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
+ XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \
SYS_CPU_NONCOHERENT_MODE * 4
/* Enable XLP features and workarounds in the LSU */
@@ -74,35 +75,67 @@
.endm
/*
- * Low level flush for L1D cache on XLP, the normal cache ops does
- * not do the complete and correct cache flush.
+ * Allow access to physical mem >64G by enabling ELPA in PAGEGRAIN
+ * register. This is needed before going to C code since the SP can
+ * in this region. Called from all HW threads.
+ */
+.macro xlp_early_mmu_init
+ mfc0 t0, CP0_PAGEMASK, 1
+ li t1, (1 << 29) /* ELPA bit */
+ or t0, t1
+ mtc0 t0, CP0_PAGEMASK, 1
+.endm
+
+/*
+ * L1D cache has to be flushed before enabling threads in XLP.
+ * On XLP8xx/XLP3xx, we do a low level flush using processor control
+ * registers. On XLPII CPUs, usual cache instructions work.
*/
.macro xlp_flush_l1_dcache
+ mfc0 t0, CP0_EBASE, 0
+ andi t0, t0, PRID_IMP_MASK
+ slt t1, t0, 0x1200
+ beqz t1, 15f
+ nop
+
+ /* XLP8xx low level cache flush */
li t0, LSU_DEBUG_DATA0
li t1, LSU_DEBUG_ADDR
li t2, 0 /* index */
li t3, 0x1000 /* loop count */
-1:
+11:
sll v0, t2, 5
mtcr zero, t0
ori v1, v0, 0x3 /* way0 | write_enable | write_active */
mtcr v1, t1
-2:
+12:
mfcr v1, t1
andi v1, 0x1 /* wait for write_active == 0 */
- bnez v1, 2b
+ bnez v1, 12b
nop
mtcr zero, t0
ori v1, v0, 0x7 /* way1 | write_enable | write_active */
mtcr v1, t1
-3:
+13:
mfcr v1, t1
andi v1, 0x1 /* wait for write_active == 0 */
- bnez v1, 3b
+ bnez v1, 13b
nop
addi t2, 1
- bne t3, t2, 1b
+ bne t3, t2, 11b
+ nop
+ b 17f
+ nop
+
+ /* XLPII CPUs, Invalidate all 64k of L1 D-cache */
+15:
+ li t0, 0x80000000
+ li t1, 0x80010000
+16: cache Index_Writeback_Inv_D, 0(t0)
+ addiu t0, t0, 32
+ bne t0, t1, 16b
nop
+17:
.endm
/*
@@ -138,6 +171,17 @@ FEXPORT(nlm_reset_entry)
nop
1: /* Entry point on core wakeup */
+ mfc0 t0, CP0_EBASE, 0 /* processor ID */
+ andi t0, PRID_IMP_MASK
+ li t1, 0x1500 /* XLP 9xx */
+ beq t0, t1, 2f /* does not need to set coherent */
+ nop
+
+ li t1, 0x1300 /* XLP 5xx */
+ beq t0, t1, 2f /* does not need to set coherent */
+ nop
+
+ /* set bit in SYS coherent register for the core */
mfc0 t0, CP0_EBASE, 1
mfc0 t1, CP0_EBASE, 1
srl t1, 5
@@ -149,7 +193,7 @@ FEXPORT(nlm_reset_entry)
li t1, 0x1
sll t0, t1, t0
nor t0, t0, zero /* t0 <- ~(1 << core) */
- li t2, SYS_CPU_COHERENT_BASE(0)
+ li t2, SYS_CPU_COHERENT_BASE
add t2, t2, t3 /* t2 <- SYS offset for node */
lw t1, 0(t2)
and t1, t1, t0
@@ -159,17 +203,20 @@ FEXPORT(nlm_reset_entry)
lw t1, 0(t2)
sync
+2:
/* Configure LSU on Non-0 Cores. */
xlp_config_lsu
/* FALL THROUGH */
/*
- * Wake up sibling threads from the initial thread in
- * a core.
+ * Wake up sibling threads from the initial thread in a core.
*/
EXPORT(nlm_boot_siblings)
/* core L1D flush before enable threads */
xlp_flush_l1_dcache
+ /* save ra and sp, will be used later (only for boot cpu) */
+ dmtc0 ra, $22, 6
+ dmtc0 sp, $22, 7
/* Enable hw threads by writing to MAP_THREADMODE of the core */
li t0, CKSEG1ADDR(RESET_DATA_PHYS)
lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */
@@ -181,8 +228,10 @@ EXPORT(nlm_boot_siblings)
/*
* The new hardware thread starts at the next instruction
* For all the cases other than core 0 thread 0, we will
- * jump to the secondary wait function.
- */
+ * jump to the secondary wait function.
+
+ * NOTE: All GPR contents are lost after the mtcr above!
+ */
mfc0 v0, CP0_EBASE, 1
andi v0, 0x3ff /* v0 <- node/core */
@@ -196,7 +245,9 @@ EXPORT(nlm_boot_siblings)
#endif
mtc0 t1, CP0_STATUS
- /* mark CPU ready, careful here, previous mtcr trashed registers */
+ xlp_early_mmu_init
+
+ /* mark CPU ready */
li t3, CKSEG1ADDR(RESET_DATA_PHYS)
ADDIU t1, t3, BOOT_CPU_READY
sll v1, v0, 2
@@ -209,14 +260,12 @@ EXPORT(nlm_boot_siblings)
nop
/*
- * For the boot CPU, we have to restore registers and
- * return
+ * For the boot CPU, we have to restore ra and sp and return, rest
+ * of the registers will be restored by the caller
*/
-4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */
- li t1, 0xfadebeef
- dmtc0 t1, $4, 2 /* restore SP from UserLocal */
- PTR_SUBU sp, t0, PT_SIZE
- RESTORE_ALL
+4:
+ dmfc0 ra, $22, 6
+ dmfc0 sp, $22, 7
jr ra
nop
EXPORT(nlm_reset_entry_end)
@@ -224,6 +273,7 @@ EXPORT(nlm_reset_entry_end)
LEAF(nlm_init_boot_cpu)
#ifdef CONFIG_CPU_XLP
xlp_config_lsu
+ xlp_early_mmu_init
#endif
jr ra
nop
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 6f8feb9efcf..4fde7ac76cc 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -63,7 +63,7 @@ void nlm_send_ipi_single(int logical_cpu, unsigned int action)
uint64_t picbase;
cpu = cpu_logical_map(logical_cpu);
- node = cpu / NLM_CPUS_PER_NODE;
+ node = nlm_cpuid_to_node(cpu);
picbase = nlm_get_node(node)->picbase;
if (action & SMP_CALL_FUNCTION)
@@ -135,10 +135,6 @@ void nlm_smp_finish(void)
local_irq_enable();
}
-void nlm_cpus_done(void)
-{
-}
-
/*
* Boot all other cpus in the system, initialize them, and bring them into
* the boot function
@@ -152,7 +148,7 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
int cpu, node;
cpu = cpu_logical_map(logical_cpu);
- node = cpu / NLM_CPUS_PER_NODE;
+ node = nlm_cpuid_to_node(logical_cpu);
nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
nlm_next_gp = (unsigned long)task_thread_info(idle);
@@ -164,7 +160,7 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
void __init nlm_smp_setup(void)
{
unsigned int boot_cpu;
- int num_cpus, i, ncore;
+ int num_cpus, i, ncore, node;
volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
char buf[64];
@@ -187,6 +183,8 @@ void __init nlm_smp_setup(void)
__cpu_number_map[i] = num_cpus;
__cpu_logical_map[num_cpus] = i;
set_cpu_possible(num_cpus, true);
+ node = nlm_cpuid_to_node(i);
+ cpumask_set_cpu(num_cpus, &nlm_get_node(node)->cpumask);
++num_cpus;
}
}
@@ -196,7 +194,7 @@ void __init nlm_smp_setup(void)
cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask);
pr_info("Possible CPU mask: %s\n", buf);
- /* check with the cores we have worken up */
+ /* check with the cores we have woken up */
for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
ncore += hweight32(nlm_get_node(i)->coremask);
@@ -211,6 +209,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
{
uint32_t core0_thr_mask, core_thr_mask;
int threadmode, i, j;
+ char buf[64];
core0_thr_mask = 0;
for (i = 0; i < NLM_THREADS_PER_CORE; i++)
@@ -245,8 +244,8 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
return threadmode;
unsupp:
- panic("Unsupported CPU mask %lx\n",
- (unsigned long)cpumask_bits(wakeup_mask)[0]);
+ cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask);
+ panic("Unsupported CPU mask %s", buf);
return 0;
}
@@ -275,7 +274,6 @@ struct plat_smp_ops nlm_smp_ops = {
.send_ipi_mask = nlm_send_ipi_mask,
.init_secondary = nlm_init_secondary,
.smp_finish = nlm_smp_finish,
- .cpus_done = nlm_cpus_done,
.boot_secondary = nlm_boot_secondary,
.smp_setup = nlm_smp_setup,
.prepare_cpus = nlm_prepare_cpus,
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
index aa6cff0a229..805355b0bd0 100644
--- a/arch/mips/netlogic/common/smpboot.S
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -32,7 +32,6 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <linux/init.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
@@ -55,8 +54,9 @@
.set noat
.set arch=xlr /* for mfcr/mtcr, XLR is sufficient */
-FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */
- dmtc0 sp, $4, 2 /* SP saved in UserLocal */
+/* Called by the boot cpu to wake up its sibling threads */
+NESTED(xlp_boot_core0_siblings, PT_SIZE, sp)
+ /* CPU register contents lost when enabling threads, save them first */
SAVE_ALL
sync
/* find the location to which nlm_boot_siblings was relocated */
@@ -66,9 +66,12 @@ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */
dsubu t2, t1
daddu t2, t0
/* call it */
- jr t2
+ jalr t2
nop
- /* not reached */
+ RESTORE_ALL
+ jr ra
+ nop
+END(xlp_boot_core0_siblings)
NESTED(nlm_boot_secondary_cpus, 16, sp)
/* Initialize CP0 Status */
@@ -98,7 +101,7 @@ END(nlm_boot_secondary_cpus)
* In case of RMIboot bootloader which is used on XLR boards, the CPUs
* be already woken up and waiting in bootloader code.
* This will get them out of the bootloader code and into linux. Needed
- * because the bootloader area will be taken and initialized by linux.
+ * because the bootloader area will be taken and initialized by linux.
*/
NESTED(nlm_rmiboot_preboot, 16, sp)
mfc0 t0, $15, 1 /* read ebase */
@@ -133,6 +136,7 @@ NESTED(nlm_rmiboot_preboot, 16, sp)
or t1, t2, v1 /* put in new value */
mtcr t1, t0 /* update core control */
+ /* wait for NMI to hit */
1: wait
b 1b
nop
diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c
index 13391b8a603..0c0a1a606f7 100644
--- a/arch/mips/netlogic/common/time.c
+++ b/arch/mips/netlogic/common/time.c
@@ -82,6 +82,7 @@ static struct clocksource csrc_pic = {
static void nlm_init_pic_timer(void)
{
uint64_t picbase = nlm_get_node(0)->picbase;
+ u32 picfreq;
nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
if (current_cpu_data.cputype == CPU_XLR) {
@@ -92,7 +93,9 @@ static void nlm_init_pic_timer(void)
csrc_pic.read = nlm_get_pic_timer;
}
csrc_pic.rating = 1000;
- clocksource_register_hz(&csrc_pic, pic_timer_freq());
+ picfreq = pic_timer_freq();
+ clocksource_register_hz(&csrc_pic, picfreq);
+ pr_info("PIC clock source added, frequency %d\n", picfreq);
}
void __init plat_time_init(void)
diff --git a/arch/mips/netlogic/dts/Makefile b/arch/mips/netlogic/dts/Makefile
index 0b9be5fd2e4..25c8e873ee2 100644
--- a/arch/mips/netlogic/dts/Makefile
+++ b/arch/mips/netlogic/dts/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_DT_XLP_EVP) := xlp_evp.dtb.o
obj-$(CONFIG_DT_XLP_SVP) += xlp_svp.dtb.o
obj-$(CONFIG_DT_XLP_FVP) += xlp_fvp.dtb.o
+obj-$(CONFIG_DT_XLP_GVP) += xlp_gvp.dtb.o
diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts
new file mode 100644
index 00000000000..bb4ecd1d47f
--- /dev/null
+++ b/arch/mips/netlogic/dts/xlp_gvp.dts
@@ -0,0 +1,77 @@
+/*
+ * XLP9XX Device Tree Source for GVP boards
+ */
+
+/dts-v1/;
+/ {
+ model = "netlogic,XLP-GVP";
+ compatible = "netlogic,xlp";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG
+ 1 0 0 0x16000000 0x02000000>; // GBU chipselects
+
+ serial0: serial@30000 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0 0x112100 0xa00>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clock-frequency = <125000000>;
+ interrupt-parent = <&pic>;
+ interrupts = <17>;
+ };
+ pic: pic@110000 {
+ compatible = "netlogic,xlp-pic";
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0 0x110000 0x200>;
+ interrupt-controller;
+ };
+
+ nor_flash@1,0 {
+ compatible = "cfi-flash";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ bank-width = <2>;
+ reg = <1 0 0x1000000>;
+
+ partition@0 {
+ label = "x-loader";
+ reg = <0x0 0x100000>; /* 1M */
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot";
+ reg = <0x100000 0x100000>; /* 1M */
+ };
+
+ partition@200000 {
+ label = "kernel";
+ reg = <0x200000 0x500000>; /* 5M */
+ };
+
+ partition@700000 {
+ label = "rootfs";
+ reg = <0x700000 0x800000>; /* 8M */
+ };
+
+ partition@f00000 {
+ label = "env";
+ reg = <0xf00000 0x100000>; /* 1M */
+ read-only;
+ };
+ };
+
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200 rdinit=/sbin/init";
+ };
+};
diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index ed9a93c0465..be358a8050c 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -2,3 +2,5 @@ obj-y += setup.o nlm_hal.o cop2-ex.o dt.o
obj-$(CONFIG_SMP) += wakeup.o
obj-$(CONFIG_USB) += usb-init.o
obj-$(CONFIG_USB) += usb-init-xlp2.o
+obj-$(CONFIG_SATA_AHCI) += ahci-init.o
+obj-$(CONFIG_SATA_AHCI) += ahci-init-xlp2.o
diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
new file mode 100644
index 00000000000..c83dbf3689e
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/pci_ids.h>
+#include <linux/nodemask.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/mips-extns.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+
+#define SATA_CTL 0x0
+#define SATA_STATUS 0x1 /* Status Reg */
+#define SATA_INT 0x2 /* Interrupt Reg */
+#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */
+#define SATA_BIU_TIMEOUT 0x4
+#define AXIWRSPERRLOG 0x5
+#define AXIRDSPERRLOG 0x6
+#define BiuTimeoutLow 0x7
+#define BiuTimeoutHi 0x8
+#define BiuSlvErLow 0x9
+#define BiuSlvErHi 0xa
+#define IO_CONFIG_SWAP_DIS 0xb
+#define CR_REG_TIMER 0xc
+#define CORE_ID 0xd
+#define AXI_SLAVE_OPT1 0xe
+#define PHY_MEM_ACCESS 0xf
+#define PHY0_CNTRL 0x10
+#define PHY0_STAT 0x11
+#define PHY0_RX_ALIGN 0x12
+#define PHY0_RX_EQ_LO 0x13
+#define PHY0_RX_EQ_HI 0x14
+#define PHY0_BIST_LOOP 0x15
+#define PHY1_CNTRL 0x16
+#define PHY1_STAT 0x17
+#define PHY1_RX_ALIGN 0x18
+#define PHY1_RX_EQ_LO 0x19
+#define PHY1_RX_EQ_HI 0x1a
+#define PHY1_BIST_LOOP 0x1b
+#define RdExBase 0x1c
+#define RdExLimit 0x1d
+#define CacheAllocBase 0x1e
+#define CacheAllocLimit 0x1f
+#define BiuSlaveCmdGstNum 0x20
+
+/*SATA_CTL Bits */
+#define SATA_RST_N BIT(0) /* Active low reset sata_core phy */
+#define SataCtlReserve0 BIT(1)
+#define M_CSYSREQ BIT(2) /* AXI master low power, not used */
+#define S_CSYSREQ BIT(3) /* AXI slave low power, not used */
+#define P0_CP_DET BIT(8) /* Reserved, bring in from pad */
+#define P0_MP_SW BIT(9) /* Mech Switch */
+#define P0_DISABLE BIT(10) /* disable p0 */
+#define P0_ACT_LED_EN BIT(11) /* Active LED enable */
+#define P0_IRST_HARD_SYNTH BIT(12) /* PHY hard synth reset */
+#define P0_IRST_HARD_TXRX BIT(13) /* PHY lane hard reset */
+#define P0_IRST_POR BIT(14) /* PHY power on reset*/
+#define P0_IPDTXL BIT(15) /* PHY Tx lane dis/power down */
+#define P0_IPDRXL BIT(16) /* PHY Rx lane dis/power down */
+#define P0_IPDIPDMSYNTH BIT(17) /* PHY synthesizer dis/porwer down */
+#define P0_CP_POD_EN BIT(18) /* CP_POD enable */
+#define P0_AT_BYPASS BIT(19) /* P0 address translation by pass */
+#define P1_CP_DET BIT(20) /* Reserved,Cold Detect */
+#define P1_MP_SW BIT(21) /* Mech Switch */
+#define P1_DISABLE BIT(22) /* disable p1 */
+#define P1_ACT_LED_EN BIT(23) /* Active LED enable */
+#define P1_IRST_HARD_SYNTH BIT(24) /* PHY hard synth reset */
+#define P1_IRST_HARD_TXRX BIT(25) /* PHY lane hard reset */
+#define P1_IRST_POR BIT(26) /* PHY power on reset*/
+#define P1_IPDTXL BIT(27) /* PHY Tx lane dis/porwer down */
+#define P1_IPDRXL BIT(28) /* PHY Rx lane dis/porwer down */
+#define P1_IPDIPDMSYNTH BIT(29) /* PHY synthesizer dis/porwer down */
+#define P1_CP_POD_EN BIT(30)
+#define P1_AT_BYPASS BIT(31) /* P1 address translation by pass */
+
+/* Status register */
+#define M_CACTIVE BIT(0) /* m_cactive, not used */
+#define S_CACTIVE BIT(1) /* s_cactive, not used */
+#define P0_PHY_READY BIT(8) /* phy is ready */
+#define P0_CP_POD BIT(9) /* Cold PowerOn */
+#define P0_SLUMBER BIT(10) /* power mode slumber */
+#define P0_PATIAL BIT(11) /* power mode patial */
+#define P0_PHY_SIG_DET BIT(12) /* phy dignal detect */
+#define P0_PHY_CALI BIT(13) /* phy calibration done */
+#define P1_PHY_READY BIT(16) /* phy is ready */
+#define P1_CP_POD BIT(17) /* Cold PowerOn */
+#define P1_SLUMBER BIT(18) /* power mode slumber */
+#define P1_PATIAL BIT(19) /* power mode patial */
+#define P1_PHY_SIG_DET BIT(20) /* phy dignal detect */
+#define P1_PHY_CALI BIT(21) /* phy calibration done */
+
+/* SATA CR_REG_TIMER bits */
+#define CR_TIME_SCALE (0x1000 << 0)
+
+/* SATA PHY specific registers start and end address */
+#define RXCDRCALFOSC0 0x0065
+#define CALDUTY 0x006e
+#define RXDPIF 0x8065
+#define PPMDRIFTMAX_HI 0x80A4
+
+#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node) \
+ nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
+#define nlm_get_sata_regbase(node) \
+ (nlm_get_sata_pcibase(node) + 0x100)
+
+/* SATA PHY config for register block 1 0x0065 .. 0x006e */
+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 */
+static const u8 sata_phy_config2[] = {
+ 0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
+ 0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
+ 0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
+ 0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
+ 0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
+ 0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
+ 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
+};
+
+const int sata_phy_debug = 0; /* set to verify PHY writes */
+
+static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+ u32 reg_val;
+
+ reg_val = nlm_read_sata_reg(regbase, off);
+ nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
+{
+ u32 reg_val;
+
+ reg_val = nlm_read_sata_reg(regbase, off);
+ nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
+{
+ nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+ (1u << 31) | (physel << 24) | (data << 16) | addr);
+ udelay(850);
+}
+
+static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
+{
+ u32 val;
+
+ nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
+ (0 << 31) | (physel << 24) | (0 << 16) | addr);
+ udelay(850);
+ val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
+ return (val >> 16) & 0xff;
+}
+
+static void config_sata_phy(u64 regbase)
+{
+ u32 port, i, reg;
+
+ for (port = 0; port < 2; port++) {
+ for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+ write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
+
+ for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+ write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
+ }
+}
+
+static void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata)
+{
+ u8 data;
+
+ data = read_phy_reg(regbase, addr, physel);
+ pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
+ addr, physel, data, data == xdata ? "TRUE" : "FALSE");
+}
+
+static void verify_sata_phy_config(u64 regbase)
+{
+ u32 port, i, reg;
+
+ for (port = 0; port < 2; port++) {
+ for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
+ check_phy_register(regbase, reg, port,
+ sata_phy_config1[i]);
+
+ for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
+ check_phy_register(regbase, reg, port,
+ sata_phy_config2[i]);
+ }
+}
+
+static void nlm_sata_firmware_init(int node)
+{
+ u32 reg_val;
+ u64 regbase;
+ int n;
+
+ pr_info("Initializing XLP9XX On-chip AHCI...\n");
+ regbase = nlm_get_sata_regbase(node);
+
+ /* Reset port0 */
+ sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+ sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+ sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+ sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+ sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+ sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+
+ /* port1 */
+ sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+ sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+ sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+ sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+ sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+ sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+ udelay(300);
+
+ /* Set PHY */
+ sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
+ sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
+ sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
+ sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
+ sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
+ sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
+
+ udelay(1000);
+ sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
+ udelay(1000);
+ sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
+ udelay(1000);
+
+ /* setup PHY */
+ config_sata_phy(regbase);
+ if (sata_phy_debug)
+ verify_sata_phy_config(regbase);
+
+ udelay(1000);
+ sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
+ sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
+ sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
+ sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
+ udelay(300);
+
+ /* Override reset in serial PHY mode */
+ sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
+ /* Set reset SATA */
+ sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+ sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
+ sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
+
+ pr_debug("Waiting for PHYs to come up.\n");
+ n = 10000;
+ do {
+ reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+ if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
+ break;
+ udelay(10);
+ } while (--n > 0);
+
+ if (reg_val & P0_PHY_READY)
+ pr_info("PHY0 is up.\n");
+ else
+ pr_info("PHY0 is down.\n");
+ if (reg_val & P1_PHY_READY)
+ pr_info("PHY1 is up.\n");
+ else
+ pr_info("PHY1 is down.\n");
+
+ pr_info("XLP AHCI Init Done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+ int node;
+
+ if (!cpu_is_xlp9xx())
+ return 0;
+ for (node = 0; node < NLM_NR_NODES; node++)
+ if (nlm_node_present(node))
+ nlm_sata_firmware_init(node);
+ return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+ u64 regbase;
+ u32 val;
+ int node;
+
+ node = data->irq / NLM_IRQS_PER_NODE;
+ regbase = nlm_get_sata_regbase(node);
+ val = nlm_read_sata_reg(regbase, SATA_INT);
+ sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+ dev->resource[5] = dev->resource[0];
+ memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+ u32 val;
+ u64 regbase;
+ int node;
+
+ /* Find end bridge function to find node */
+ node = xlp_socdev_to_node(dev);
+ regbase = nlm_get_sata_regbase(node);
+
+ /* clear pending interrupts and then enable them */
+ val = nlm_read_sata_reg(regbase, SATA_INT);
+ sata_set_glue_reg(regbase, SATA_INT, val);
+
+ /* Enable only the core interrupt */
+ sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+ dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
+ nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+ nlm_sata_fixup_bar);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
+ nlm_sata_fixup_final);
diff --git a/arch/mips/netlogic/xlp/ahci-init.c b/arch/mips/netlogic/xlp/ahci-init.c
new file mode 100644
index 00000000000..a9d0fae0210
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2003-2014 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/xlp-hal/iomap.h>
+#include <asm/netlogic/mips-extns.h>
+
+#define SATA_CTL 0x0
+#define SATA_STATUS 0x1 /* Status Reg */
+#define SATA_INT 0x2 /* Interrupt Reg */
+#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */
+#define SATA_CR_REG_TIMER 0x4 /* PHY Conrol Timer Reg */
+#define SATA_CORE_ID 0x5 /* Core ID Reg */
+#define SATA_AXI_SLAVE_OPT1 0x6 /* AXI Slave Options Reg */
+#define SATA_PHY_LOS_LEV 0x7 /* PHY LOS Level Reg */
+#define SATA_PHY_MULTI 0x8 /* PHY Multiplier Reg */
+#define SATA_PHY_CLK_SEL 0x9 /* Clock Select Reg */
+#define SATA_PHY_AMP1_GEN1 0xa /* PHY Transmit Amplitude Reg 1 */
+#define SATA_PHY_AMP1_GEN2 0xb /* PHY Transmit Amplitude Reg 2 */
+#define SATA_PHY_AMP1_GEN3 0xc /* PHY Transmit Amplitude Reg 3 */
+#define SATA_PHY_PRE1 0xd /* PHY Transmit Preemphasis Reg 1 */
+#define SATA_PHY_PRE2 0xe /* PHY Transmit Preemphasis Reg 2 */
+#define SATA_PHY_PRE3 0xf /* PHY Transmit Preemphasis Reg 3 */
+#define SATA_SPDMODE 0x10 /* Speed Mode Reg */
+#define SATA_REFCLK 0x11 /* Reference Clock Control Reg */
+#define SATA_BYTE_SWAP_DIS 0x12 /* byte swap disable */
+
+/*SATA_CTL Bits */
+#define SATA_RST_N BIT(0)
+#define PHY0_RESET_N BIT(16)
+#define PHY1_RESET_N BIT(17)
+#define PHY2_RESET_N BIT(18)
+#define PHY3_RESET_N BIT(19)
+#define M_CSYSREQ BIT(2)
+#define S_CSYSREQ BIT(3)
+
+/*SATA_STATUS Bits */
+#define P0_PHY_READY BIT(4)
+#define P1_PHY_READY BIT(5)
+#define P2_PHY_READY BIT(6)
+#define P3_PHY_READY BIT(7)
+
+#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v)
+#define nlm_get_sata_pcibase(node) \
+ nlm_pcicfg_base(XLP_IO_SATA_OFFSET(node))
+/* SATA device specific configuration registers are starts at 0x900 offset */
+#define nlm_get_sata_regbase(node) \
+ (nlm_get_sata_pcibase(node) + 0x900)
+
+static void sata_clear_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
+{
+ uint32_t reg_val;
+
+ reg_val = nlm_read_sata_reg(regbase, off);
+ nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
+}
+
+static void sata_set_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
+{
+ uint32_t reg_val;
+
+ reg_val = nlm_read_sata_reg(regbase, off);
+ nlm_write_sata_reg(regbase, off, (reg_val | bit));
+}
+
+static void nlm_sata_firmware_init(int node)
+{
+ uint32_t reg_val;
+ uint64_t regbase;
+ int i;
+
+ pr_info("XLP AHCI Initialization started.\n");
+ regbase = nlm_get_sata_regbase(node);
+
+ /* Reset SATA */
+ sata_clear_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+ /* Reset PHY */
+ sata_clear_glue_reg(regbase, SATA_CTL,
+ (PHY3_RESET_N | PHY2_RESET_N
+ | PHY1_RESET_N | PHY0_RESET_N));
+
+ /* Set SATA */
+ sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
+ /* Set PHY */
+ sata_set_glue_reg(regbase, SATA_CTL,
+ (PHY3_RESET_N | PHY2_RESET_N
+ | PHY1_RESET_N | PHY0_RESET_N));
+
+ pr_debug("Waiting for PHYs to come up.\n");
+ i = 0;
+ do {
+ reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
+ i++;
+ } while (((reg_val & 0xF0) != 0xF0) && (i < 10000));
+
+ for (i = 0; i < 4; i++) {
+ if (reg_val & (P0_PHY_READY << i))
+ pr_info("PHY%d is up.\n", i);
+ else
+ pr_info("PHY%d is down.\n", i);
+ }
+
+ pr_info("XLP AHCI init done.\n");
+}
+
+static int __init nlm_ahci_init(void)
+{
+ int node = 0;
+ int chip = read_c0_prid() & PRID_REV_MASK;
+
+ if (chip == PRID_IMP_NETLOGIC_XLP3XX)
+ nlm_sata_firmware_init(node);
+ return 0;
+}
+
+static void nlm_sata_intr_ack(struct irq_data *data)
+{
+ uint32_t val = 0;
+ uint64_t regbase;
+
+ regbase = nlm_get_sata_regbase(nlm_nodeid());
+ val = nlm_read_sata_reg(regbase, SATA_INT);
+ sata_set_glue_reg(regbase, SATA_INT, val);
+}
+
+static void nlm_sata_fixup_bar(struct pci_dev *dev)
+{
+ /*
+ * The AHCI resource is in BAR 0, move it to
+ * BAR 5, where it is expected
+ */
+ dev->resource[5] = dev->resource[0];
+ memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
+}
+
+static void nlm_sata_fixup_final(struct pci_dev *dev)
+{
+ uint32_t val;
+ uint64_t regbase;
+ int node = 0; /* XLP3XX does not support multi-node */
+
+ regbase = nlm_get_sata_regbase(node);
+
+ /* clear pending interrupts and then enable them */
+ val = nlm_read_sata_reg(regbase, SATA_INT);
+ sata_set_glue_reg(regbase, SATA_INT, val);
+
+ /* Mask the core interrupt. If all the interrupts
+ * are enabled there are spurious interrupt flow
+ * happening, to avoid only enable core interrupt
+ * mask.
+ */
+ sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
+
+ dev->irq = PIC_SATA_IRQ;
+ nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
+}
+
+arch_initcall(nlm_ahci_init);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
+ nlm_sata_fixup_bar);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
+ nlm_sata_fixup_final);
diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c
index 88df445dda7..7cc46032b28 100644
--- a/arch/mips/netlogic/xlp/dt.c
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -39,13 +39,22 @@
#include <linux/of_platform.h>
#include <linux/of_device.h>
+#include <asm/prom.h>
+
extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[],
- __dtb_xlp_fvp_begin[], __dtb_start[];
+ __dtb_xlp_fvp_begin[], __dtb_xlp_gvp_begin[];
+static void *xlp_fdt_blob;
void __init *xlp_dt_init(void *fdtp)
{
if (!fdtp) {
- switch (current_cpu_data.processor_id & 0xff00) {
+ switch (current_cpu_data.processor_id & PRID_IMP_MASK) {
+#ifdef CONFIG_DT_XLP_GVP
+ case PRID_IMP_NETLOGIC_XLP9XX:
+ case PRID_IMP_NETLOGIC_XLP5XX:
+ fdtp = __dtb_xlp_gvp_begin;
+ break;
+#endif
#ifdef CONFIG_DT_XLP_FVP
case PRID_IMP_NETLOGIC_XLP2XX:
fdtp = __dtb_xlp_fvp_begin;
@@ -67,27 +76,19 @@ void __init *xlp_dt_init(void *fdtp)
break;
}
}
- initial_boot_params = fdtp;
+ xlp_fdt_blob = fdtp;
return fdtp;
}
-void __init device_tree_init(void)
+void __init xlp_early_init_devtree(void)
{
- unsigned long base, size;
-
- if (!initial_boot_params)
- return;
-
- base = virt_to_phys((void *)initial_boot_params);
- size = be32_to_cpu(initial_boot_params->totalsize);
-
- /* Before we do anything, lets reserve the dt blob */
- reserve_bootmem(base, size, BOOTMEM_DEFAULT);
-
- unflatten_device_tree();
+ __dt_setup_arch(xlp_fdt_blob);
+ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+}
- /* free the space reserved for the dt blob */
- free_bootmem(base, size);
+void __init device_tree_init(void)
+{
+ unflatten_and_copy_device_tree();
}
static struct of_device_id __initdata xlp_ids[] = {
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index 56c50ba43c9..bc24beb3a42 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -54,13 +54,47 @@ void nlm_node_init(int node)
struct nlm_soc_info *nodep;
nodep = nlm_get_node(node);
+ if (node == 0)
+ nodep->coremask = 1; /* node 0, boot cpu */
nodep->sysbase = nlm_get_sys_regbase(node);
nodep->picbase = nlm_get_pic_regbase(node);
nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+ if (cpu_is_xlp9xx())
+ nodep->socbus = xlp9xx_get_socbus(node);
+ else
+ nodep->socbus = 0;
spin_lock_init(&nodep->piclock);
}
-int nlm_irq_to_irt(int irq)
+static int xlp9xx_irq_to_irt(int irq)
+{
+ switch (irq) {
+ case PIC_GPIO_IRQ:
+ return 12;
+ case PIC_9XX_XHCI_0_IRQ:
+ return 114;
+ case PIC_9XX_XHCI_1_IRQ:
+ return 115;
+ case PIC_UART_0_IRQ:
+ return 133;
+ case PIC_UART_1_IRQ:
+ return 134;
+ case PIC_SATA_IRQ:
+ return 143;
+ case PIC_SPI_IRQ:
+ return 152;
+ case PIC_MMC_IRQ:
+ return 153;
+ case PIC_PCIE_LINK_LEGACY_IRQ(0):
+ case PIC_PCIE_LINK_LEGACY_IRQ(1):
+ case PIC_PCIE_LINK_LEGACY_IRQ(2):
+ case PIC_PCIE_LINK_LEGACY_IRQ(3):
+ return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
+ }
+ return -1;
+}
+
+static int xlp_irq_to_irt(int irq)
{
uint64_t pcibase;
int devoff, irt;
@@ -74,7 +108,7 @@ int nlm_irq_to_irt(int irq)
devoff = XLP_IO_UART1_OFFSET(0);
break;
case PIC_MMC_IRQ:
- devoff = XLP_IO_SD_OFFSET(0);
+ devoff = XLP_IO_MMC_OFFSET(0);
break;
case PIC_I2C_0_IRQ: /* I2C will be fixed up */
case PIC_I2C_1_IRQ:
@@ -85,6 +119,18 @@ int nlm_irq_to_irt(int irq)
else
devoff = XLP_IO_I2C0_OFFSET(0);
break;
+ case PIC_SATA_IRQ:
+ devoff = XLP_IO_SATA_OFFSET(0);
+ break;
+ case PIC_GPIO_IRQ:
+ devoff = XLP_IO_GPIO_OFFSET(0);
+ break;
+ case PIC_NAND_IRQ:
+ devoff = XLP_IO_NAND_OFFSET(0);
+ break;
+ case PIC_SPI_IRQ:
+ devoff = XLP_IO_SPI_OFFSET(0);
+ break;
default:
if (cpu_is_xlpii()) {
switch (irq) {
@@ -135,16 +181,78 @@ int nlm_irq_to_irt(int irq)
case PIC_I2C_3_IRQ:
irt = irt + 3; break;
}
- } else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) {
+ } else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) &&
+ irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) {
/* HW bug, PCI IRT entries are bad on early silicon, fix */
- irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ);
+ irt = PIC_IRT_PCIE_LINK_INDEX(irq -
+ PIC_PCIE_LINK_LEGACY_IRQ_BASE);
} else {
irt = -1;
}
return irt;
}
-unsigned int nlm_get_core_frequency(int node, int core)
+int nlm_irq_to_irt(int irq)
+{
+ /* return -2 for irqs without 1-1 mapping */
+ if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
+ return -2;
+ if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
+ return -2;
+
+ if (cpu_is_xlp9xx())
+ return xlp9xx_irq_to_irt(irq);
+ else
+ return xlp_irq_to_irt(irq);
+}
+
+static unsigned int nlm_xlp2_get_core_frequency(int node, int core)
+{
+ unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom;
+ uint64_t num, sysbase, clockbase;
+
+ if (cpu_is_xlp9xx()) {
+ clockbase = nlm_get_clock_regbase(node);
+ ctrl_val0 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_CPU_PLL_CTRL0(core));
+ ctrl_val1 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_CPU_PLL_CTRL1(core));
+ } else {
+ sysbase = nlm_get_node(node)->sysbase;
+ ctrl_val0 = nlm_read_sys_reg(sysbase,
+ SYS_CPU_PLL_CTRL0(core));
+ ctrl_val1 = nlm_read_sys_reg(sysbase,
+ SYS_CPU_PLL_CTRL1(core));
+ }
+
+ /* Find PLL post divider value */
+ switch ((ctrl_val0 >> 24) & 0x7) {
+ case 1:
+ pll_post_div = 2;
+ break;
+ case 3:
+ pll_post_div = 4;
+ break;
+ case 7:
+ pll_post_div = 8;
+ break;
+ case 6:
+ pll_post_div = 16;
+ break;
+ case 0:
+ default:
+ pll_post_div = 1;
+ break;
+ }
+
+ num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f));
+ denom = 3 * pll_post_div;
+ do_div(num, denom);
+
+ return (unsigned int)num;
+}
+
+static unsigned int nlm_xlp_get_core_frequency(int node, int core)
{
unsigned int pll_divf, pll_divr, dfs_div, ext_div;
unsigned int rstval, dfsval, denom;
@@ -152,38 +260,49 @@ unsigned int nlm_get_core_frequency(int node, int core)
sysbase = nlm_get_node(node)->sysbase;
rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
- if (cpu_is_xlpii()) {
- num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26));
- denom = 3;
- } else {
- dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
- pll_divf = ((rstval >> 10) & 0x7f) + 1;
- pll_divr = ((rstval >> 8) & 0x3) + 1;
- ext_div = ((rstval >> 30) & 0x3) + 1;
- dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1;
-
- num = 800000000ULL * pll_divf;
- denom = 3 * pll_divr * ext_div * dfs_div;
- }
+ dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
+ pll_divf = ((rstval >> 10) & 0x7f) + 1;
+ pll_divr = ((rstval >> 8) & 0x3) + 1;
+ ext_div = ((rstval >> 30) & 0x3) + 1;
+ dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1;
+
+ num = 800000000ULL * pll_divf;
+ denom = 3 * pll_divr * ext_div * dfs_div;
do_div(num, denom);
+
return (unsigned int)num;
}
-/* Calculate Frequency to the PIC from PLL.
- * freq_out = ( ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13 ) /
- * ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
+unsigned int nlm_get_core_frequency(int node, int core)
+{
+ if (cpu_is_xlpii())
+ return nlm_xlp2_get_core_frequency(node, core);
+ else
+ return nlm_xlp_get_core_frequency(node, core);
+}
+
+/*
+ * Calculate PIC frequency from PLL registers.
+ * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
+ * ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
*/
-static unsigned int nlm_2xx_get_pic_frequency(int node)
+static unsigned int nlm_xlp2_get_pic_frequency(int node)
{
- u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div;
+ u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx;
u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div;
- u64 ref_clk, sysbase, pll_out_freq_num, ref_clk_select;
+ u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk;
sysbase = nlm_get_node(node)->sysbase;
+ clockbase = nlm_get_clock_regbase(node);
+ cpu_xlp9xx = cpu_is_xlp9xx();
/* Find ref_clk_base */
- ref_clk_select =
- (nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
+ if (cpu_xlp9xx)
+ ref_clk_select = (nlm_read_sys_reg(sysbase,
+ SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3;
+ else
+ ref_clk_select = (nlm_read_sys_reg(sysbase,
+ SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
switch (ref_clk_select) {
case 0:
ref_clk = 200000000ULL;
@@ -204,30 +323,70 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
}
/* Find the clock source PLL device for PIC */
- reg_select = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_SEL) >> 22) & 0x3;
- switch (reg_select) {
- case 0:
- ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0);
- ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2);
- break;
- case 1:
- ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(0));
- ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(0));
- break;
- case 2:
- ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(1));
- ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(1));
- break;
- case 3:
- ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(2));
- ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(2));
- break;
+ if (cpu_xlp9xx) {
+ reg_select = nlm_read_sys_reg(clockbase,
+ SYS_9XX_CLK_DEV_SEL) & 0x3;
+ switch (reg_select) {
+ case 0:
+ ctrl_val0 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL0);
+ ctrl_val2 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL2);
+ break;
+ case 1:
+ ctrl_val0 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL0_DEVX(0));
+ ctrl_val2 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL2_DEVX(0));
+ break;
+ case 2:
+ ctrl_val0 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL0_DEVX(1));
+ ctrl_val2 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL2_DEVX(1));
+ break;
+ case 3:
+ ctrl_val0 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL0_DEVX(2));
+ ctrl_val2 = nlm_read_sys_reg(clockbase,
+ SYS_9XX_PLL_CTRL2_DEVX(2));
+ break;
+ }
+ } else {
+ reg_select = (nlm_read_sys_reg(sysbase,
+ SYS_CLK_DEV_SEL) >> 22) & 0x3;
+ switch (reg_select) {
+ case 0:
+ ctrl_val0 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL0);
+ ctrl_val2 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL2);
+ break;
+ case 1:
+ ctrl_val0 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL0_DEVX(0));
+ ctrl_val2 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL2_DEVX(0));
+ break;
+ case 2:
+ ctrl_val0 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL0_DEVX(1));
+ ctrl_val2 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL2_DEVX(1));
+ break;
+ case 3:
+ ctrl_val0 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL0_DEVX(2));
+ ctrl_val2 = nlm_read_sys_reg(sysbase,
+ SYS_PLL_CTRL2_DEVX(2));
+ break;
+ }
}
vco_post_div = (ctrl_val0 >> 5) & 0x7;
pll_post_div = (ctrl_val0 >> 24) & 0x7;
mdiv = ctrl_val2 & 0xff;
- fdiv = (ctrl_val2 >> 8) & 0xfff;
+ fdiv = (ctrl_val2 >> 8) & 0x1fff;
/* Find PLL post divider value */
switch (pll_post_div) {
@@ -257,7 +416,12 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
do_div(pll_out_freq_num, pll_out_freq_den);
/* PIC post divider, which happens after PLL */
- pic_div = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_DIV) >> 22) & 0x3;
+ if (cpu_xlp9xx)
+ pic_div = nlm_read_sys_reg(clockbase,
+ SYS_9XX_CLK_DEV_DIV) & 0x3;
+ else
+ pic_div = (nlm_read_sys_reg(sysbase,
+ SYS_CLK_DEV_DIV) >> 22) & 0x3;
do_div(pll_out_freq_num, 1 << pic_div);
return pll_out_freq_num;
@@ -266,7 +430,7 @@ static unsigned int nlm_2xx_get_pic_frequency(int node)
unsigned int nlm_get_pic_frequency(int node)
{
if (cpu_is_xlpii())
- return nlm_2xx_get_pic_frequency(node);
+ return nlm_xlp2_get_pic_frequency(node);
else
return 133333333;
}
@@ -284,21 +448,33 @@ int xlp_get_dram_map(int n, uint64_t *dram_map)
{
uint64_t bridgebase, base, lim;
uint32_t val;
+ unsigned int barreg, limreg, xlatreg;
int i, node, rv;
/* Look only at mapping on Node 0, we don't handle crazy configs */
bridgebase = nlm_get_bridge_regbase(0);
rv = 0;
for (i = 0; i < 8; i++) {
- val = nlm_read_bridge_reg(bridgebase,
- BRIDGE_DRAM_NODE_TRANSLN(i));
- node = (val >> 1) & 0x3;
- if (n >= 0 && n != node)
- continue;
- val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_BAR(i));
+ if (cpu_is_xlp9xx()) {
+ barreg = BRIDGE_9XX_DRAM_BAR(i);
+ limreg = BRIDGE_9XX_DRAM_LIMIT(i);
+ xlatreg = BRIDGE_9XX_DRAM_NODE_TRANSLN(i);
+ } else {
+ barreg = BRIDGE_DRAM_BAR(i);
+ limreg = BRIDGE_DRAM_LIMIT(i);
+ xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i);
+ }
+ if (n >= 0) {
+ /* node specified, get node mapping of BAR */
+ val = nlm_read_bridge_reg(bridgebase, xlatreg);
+ node = (val >> 1) & 0x3;
+ if (n != node)
+ continue;
+ }
+ val = nlm_read_bridge_reg(bridgebase, barreg);
val = (val >> 12) & 0xfffff;
base = (uint64_t) val << 20;
- val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_LIMIT(i));
+ val = nlm_read_bridge_reg(bridgebase, limreg);
val = (val >> 12) & 0xfffff;
if (val == 0) /* BAR not used */
continue;
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 76a7131e486..4fdd9fd29d1 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -51,12 +51,16 @@ uint64_t nlm_io_base;
struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
cpumask_t nlm_cpumask = CPU_MASK_CPU0;
unsigned int nlm_threads_per_core;
+unsigned int xlp_cores_per_node;
static void nlm_linux_exit(void)
{
uint64_t sysbase = nlm_get_node(0)->sysbase;
- nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
+ if (cpu_is_xlp9xx())
+ nlm_write_sys_reg(sysbase, SYS_9XX_CHIP_RESET, 1);
+ else
+ nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
for ( ; ; )
cpu_wait();
}
@@ -92,13 +96,20 @@ static void __init xlp_init_mem_from_bars(void)
void __init plat_mem_setup(void)
{
- panic_timeout = 5;
+#ifdef CONFIG_SMP
+ nlm_wakeup_secondary_cpus();
+
+ /* update TLB size after waking up threads */
+ current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
+
+ register_smp_ops(&nlm_smp_ops);
+#endif
_machine_restart = (void (*)(char *))nlm_linux_exit;
_machine_halt = nlm_linux_exit;
pm_power_off = nlm_linux_exit;
/* memory and bootargs from DT */
- early_init_devtree(initial_boot_params);
+ xlp_early_init_devtree();
if (boot_mem_map.nr_map == 0) {
pr_info("Using DRAM BARs for memory map.\n");
@@ -110,7 +121,9 @@ void __init plat_mem_setup(void)
const char *get_system_type(void)
{
- switch (read_c0_prid() & 0xff00) {
+ switch (read_c0_prid() & PRID_IMP_MASK) {
+ case PRID_IMP_NETLOGIC_XLP9XX:
+ case PRID_IMP_NETLOGIC_XLP5XX:
case PRID_IMP_NETLOGIC_XLP2XX:
return "Broadcom XLPII Series";
default:
@@ -150,6 +163,10 @@ void __init prom_init(void)
void *reset_vec;
nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
+ if (cpu_is_xlp9xx())
+ xlp_cores_per_node = 32;
+ else
+ xlp_cores_per_node = 8;
nlm_init_boot_cpu();
xlp_mmu_init();
nlm_node_init(0);
@@ -163,11 +180,5 @@ void __init prom_init(void)
#ifdef CONFIG_SMP
cpumask_setall(&nlm_cpumask);
- nlm_wakeup_secondary_cpus();
-
- /* update TLB size after waking up threads */
- current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
-
- register_smp_ops(&nlm_smp_ops);
#endif
}
diff --git a/arch/mips/netlogic/xlp/usb-init-xlp2.c b/arch/mips/netlogic/xlp/usb-init-xlp2.c
index 36e9c22afc4..17ade1ce5df 100644
--- a/arch/mips/netlogic/xlp/usb-init-xlp2.c
+++ b/arch/mips/netlogic/xlp/usb-init-xlp2.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/pci_ids.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
@@ -83,12 +84,14 @@
#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v)
-#define nlm_xlpii_get_usb_pcibase(node, inst) \
- nlm_pcicfg_base(XLP2XX_IO_USB_OFFSET(node, inst))
+#define nlm_xlpii_get_usb_pcibase(node, inst) \
+ nlm_pcicfg_base(cpu_is_xlp9xx() ? \
+ XLP9XX_IO_USB_OFFSET(node, inst) : \
+ XLP2XX_IO_USB_OFFSET(node, inst))
#define nlm_xlpii_get_usb_regbase(node, inst) \
(nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
-static void xlpii_usb_ack(struct irq_data *data)
+static void xlp2xx_usb_ack(struct irq_data *data)
{
u64 port_addr;
@@ -109,6 +112,29 @@ static void xlpii_usb_ack(struct irq_data *data)
nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
}
+static void xlp9xx_usb_ack(struct irq_data *data)
+{
+ u64 port_addr;
+ int node, irq;
+
+ /* Find the node and irq on the node */
+ irq = data->irq % NLM_IRQS_PER_NODE;
+ node = data->irq / NLM_IRQS_PER_NODE;
+
+ switch (irq) {
+ case PIC_9XX_XHCI_0_IRQ:
+ port_addr = nlm_xlpii_get_usb_regbase(node, 1);
+ break;
+ case PIC_9XX_XHCI_1_IRQ:
+ port_addr = nlm_xlpii_get_usb_regbase(node, 2);
+ break;
+ default:
+ pr_err("No matching USB irq %d node %d!\n", irq, node);
+ return;
+ }
+ nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
+}
+
static void nlm_xlpii_usb_hw_reset(int node, int port)
{
u64 port_addr, xhci_base, pci_base;
@@ -178,17 +204,33 @@ static void nlm_xlpii_usb_hw_reset(int node, int port)
static int __init nlm_platform_xlpii_usb_init(void)
{
+ int node;
+
if (!cpu_is_xlpii())
return 0;
- pr_info("Initializing 2XX USB Interface\n");
- nlm_xlpii_usb_hw_reset(0, 1);
- nlm_xlpii_usb_hw_reset(0, 2);
- nlm_xlpii_usb_hw_reset(0, 3);
- nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlpii_usb_ack);
- nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlpii_usb_ack);
- nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlpii_usb_ack);
+ if (!cpu_is_xlp9xx()) {
+ /* XLP 2XX single node */
+ pr_info("Initializing 2XX USB Interface\n");
+ nlm_xlpii_usb_hw_reset(0, 1);
+ nlm_xlpii_usb_hw_reset(0, 2);
+ nlm_xlpii_usb_hw_reset(0, 3);
+ nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack);
+ nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack);
+ nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack);
+ return 0;
+ }
+ /* XLP 9XX, multi-node */
+ pr_info("Initializing 9XX USB Interface\n");
+ for (node = 0; node < NLM_NR_NODES; node++) {
+ if (!nlm_node_present(node))
+ continue;
+ nlm_xlpii_usb_hw_reset(node, 1);
+ nlm_xlpii_usb_hw_reset(node, 2);
+ nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack);
+ nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack);
+ }
return 0;
}
@@ -196,8 +238,26 @@ arch_initcall(nlm_platform_xlpii_usb_init);
static u64 xlp_usb_dmamask = ~(u32)0;
-/* Fixup IRQ for USB devices on XLP the SoC PCIe bus */
-static void nlm_usb_fixup_final(struct pci_dev *dev)
+/* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */
+static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev)
+{
+ int node;
+
+ node = xlp_socdev_to_node(dev);
+ dev->dev.dma_mask = &xlp_usb_dmamask;
+ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ switch (dev->devfn) {
+ case 0x21:
+ dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ);
+ break;
+ case 0x22:
+ dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ);
+ break;
+ }
+}
+
+/* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */
+static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev)
{
dev->dev.dma_mask = &xlp_usb_dmamask;
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
@@ -214,5 +274,7 @@ static void nlm_usb_fixup_final(struct pci_dev *dev)
}
}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI,
+ nlm_xlp9xx_usb_fixup_final);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI,
- nlm_usb_fixup_final);
+ nlm_xlp2xx_usb_fixup_final);
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 682d5638dc0..e5f44d2605a 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -32,7 +32,6 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/threads.h>
@@ -47,14 +46,14 @@
#include <asm/netlogic/mips-extns.h>
#include <asm/netlogic/xlp-hal/iomap.h>
-#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/sys.h>
static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
{
uint32_t coremask, value;
- int count;
+ int count, resetreg;
coremask = (1 << core);
@@ -65,12 +64,24 @@ static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
}
+ /* On 9XX, mark coherent first */
+ if (cpu_is_xlp9xx()) {
+ value = nlm_read_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE);
+ value &= ~coremask;
+ nlm_write_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE, value);
+ }
+
/* Remove CPU Reset */
- value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
+ resetreg = cpu_is_xlp9xx() ? SYS_9XX_CPU_RESET : SYS_CPU_RESET;
+ value = nlm_read_sys_reg(sysbase, resetreg);
value &= ~coremask;
- nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value);
+ nlm_write_sys_reg(sysbase, resetreg, value);
+
+ /* We are done on 9XX */
+ if (cpu_is_xlp9xx())
+ return 1;
- /* Poll for CPU to mark itself coherent */
+ /* Poll for CPU to mark itself coherent on other type of XLP */
count = 100000;
do {
value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
@@ -84,7 +95,7 @@ static int wait_for_cpus(int cpu, int bootcpu)
volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
int i, count, notready;
- count = 0x20000000;
+ count = 0x800000;
do {
notready = nlm_threads_per_core;
for (i = 0; i < nlm_threads_per_core; i++)
@@ -98,27 +109,66 @@ static int wait_for_cpus(int cpu, int bootcpu)
static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
{
struct nlm_soc_info *nodep;
- uint64_t syspcibase;
- uint32_t syscoremask;
+ uint64_t syspcibase, fusebase;
+ uint32_t syscoremask, mask, fusemask;
int core, n, cpu;
for (n = 0; n < NLM_NR_NODES; n++) {
- syspcibase = nlm_get_sys_pcibase(n);
- if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
- break;
+ if (n != 0) {
+ /* check if node exists and is online */
+ if (cpu_is_xlp9xx()) {
+ int b = xlp9xx_get_socbus(n);
+ pr_info("Node %d SoC PCI bus %d.\n", n, b);
+ if (b == 0)
+ break;
+ } else {
+ syspcibase = nlm_get_sys_pcibase(n);
+ if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
+ break;
+ }
+ nlm_node_init(n);
+ }
/* read cores in reset from SYS */
- if (n != 0)
- nlm_node_init(n);
nodep = nlm_get_node(n);
- syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET);
- /* The boot cpu */
- if (n == 0) {
- syscoremask |= 1;
- nodep->coremask = 1;
+
+ if (cpu_is_xlp9xx()) {
+ fusebase = nlm_get_fuse_regbase(n);
+ fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6);
+ switch (read_c0_prid() & PRID_IMP_MASK) {
+ case PRID_IMP_NETLOGIC_XLP5XX:
+ mask = 0xff;
+ break;
+ case PRID_IMP_NETLOGIC_XLP9XX:
+ default:
+ mask = 0xfffff;
+ break;
+ }
+ } else {
+ fusemask = nlm_read_sys_reg(nodep->sysbase,
+ SYS_EFUSE_DEVICE_CFG_STATUS0);
+ switch (read_c0_prid() & PRID_IMP_MASK) {
+ case PRID_IMP_NETLOGIC_XLP3XX:
+ mask = 0xf;
+ break;
+ case PRID_IMP_NETLOGIC_XLP2XX:
+ mask = 0x3;
+ break;
+ case PRID_IMP_NETLOGIC_XLP8XX:
+ default:
+ mask = 0xff;
+ break;
+ }
}
- for (core = 0; core < NLM_CORES_PER_NODE; core++) {
+ /*
+ * Fused out cores are set in the fusemask, and the remaining
+ * cores are renumbered to range 0 .. nactive-1
+ */
+ syscoremask = (1 << hweight32(~fusemask & mask)) - 1;
+
+ pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask);
+ for (core = 0; core < nlm_cores_per_node(); core++) {
/* we will be on node 0 core 0 */
if (n == 0 && core == 0)
continue;
@@ -128,7 +178,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
continue;
/* see if at least the first hw thread is enabled */
- cpu = (n * NLM_CORES_PER_NODE + core)
+ cpu = (n * nlm_cores_per_node() + core)
* NLM_THREADS_PER_CORE;
if (!cpumask_test_cpu(cpu, wakeup_mask))
continue;
@@ -141,7 +191,8 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
nodep->coremask |= 1u << core;
/* spin until the hw threads sets their ready */
- wait_for_cpus(cpu, 0);
+ if (!wait_for_cpus(cpu, 0))
+ pr_err("Node %d : timeout core %d\n", n, core);
}
}
}
@@ -153,7 +204,8 @@ void xlp_wakeup_secondary_cpus()
* first wakeup core 0 threads
*/
xlp_boot_core0_siblings();
- wait_for_cpus(0, 0);
+ if (!wait_for_cpus(0, 0))
+ pr_err("Node 0 : timeout core 0\n");
/* now get other cores out of reset */
xlp_enable_secondary_cores(&nlm_cpumask);
diff --git a/arch/mips/netlogic/xlr/fmn-config.c b/arch/mips/netlogic/xlr/fmn-config.c
index ed3bf0e3f30..c7622c6e5f6 100644
--- a/arch/mips/netlogic/xlr/fmn-config.c
+++ b/arch/mips/netlogic/xlr/fmn-config.c
@@ -36,6 +36,7 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/netlogic/xlr/fmn.h>
#include <asm/netlogic/xlr/xlr.h>
@@ -187,7 +188,7 @@ void xlr_board_info_setup(void)
int processor_id, num_core;
num_core = hweight32(nlm_current_node()->coremask);
- processor_id = read_c0_prid() & 0xff00;
+ processor_id = read_c0_prid() & PRID_IMP_MASK;
setup_cpu_fmninfo(cpu, num_core);
switch (processor_id) {
diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c
index 7b96a91f477..4785932af24 100644
--- a/arch/mips/netlogic/xlr/platform.c
+++ b/arch/mips/netlogic/xlr/platform.c
@@ -23,7 +23,7 @@
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/xlr.h>
-unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset)
+static unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset)
{
uint64_t uartbase;
unsigned int value;
@@ -41,7 +41,7 @@ unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset)
return value;
}
-void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)
+static void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)
{
uint64_t uartbase;
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
index 214d123b79f..d118b9aa764 100644
--- a/arch/mips/netlogic/xlr/setup.c
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -60,25 +60,6 @@ unsigned int nlm_threads_per_core = 1;
struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
cpumask_t nlm_cpumask = CPU_MASK_CPU0;
-static void __init nlm_early_serial_setup(void)
-{
- struct uart_port s;
- unsigned long uart_base;
-
- uart_base = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET);
- memset(&s, 0, sizeof(s));
- s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
- s.iotype = UPIO_MEM32;
- s.regshift = 2;
- s.irq = PIC_UART_0_IRQ;
- s.uartclk = PIC_CLK_HZ;
- s.serial_in = nlm_xlr_uart_in;
- s.serial_out = nlm_xlr_uart_out;
- s.mapbase = uart_base;
- s.membase = (unsigned char __iomem *)uart_base;
- early_serial_setup(&s);
-}
-
static void nlm_linux_exit(void)
{
uint64_t gpiobase;
@@ -92,7 +73,6 @@ static void nlm_linux_exit(void)
void __init plat_mem_setup(void)
{
- panic_timeout = 5;
_machine_restart = (void (*)(char *))nlm_linux_exit;
_machine_halt = nlm_linux_exit;
pm_power_off = nlm_linux_exit;
@@ -215,7 +195,6 @@ void __init prom_init(void)
memcpy(reset_vec, (void *)nlm_reset_entry,
(nlm_reset_entry_end - nlm_reset_entry));
- nlm_early_serial_setup();
build_arcs_cmdline(argv);
prom_add_memory();
diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c
index 9fb81fa6272..d61cba1e9c6 100644
--- a/arch/mips/netlogic/xlr/wakeup.c
+++ b/arch/mips/netlogic/xlr/wakeup.c
@@ -32,7 +32,6 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <linux/init.h>
#include <linux/delay.h>
#include <linux/threads.h>
@@ -70,7 +69,7 @@ int xlr_wakeup_secondary_cpus(void)
/* Fill up the coremask early */
nodep->coremask = 1;
- for (i = 1; i < NLM_CORES_PER_NODE; i++) {
+ for (i = 1; i < nlm_cores_per_node(); i++) {
for (j = 1000000; j > 0; j--) {
if (cpu_ready[i * NLM_THREADS_PER_CORE])
break;
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 5e5424753b5..e7473244947 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -12,6 +12,7 @@
#include <linux/oprofile.h>
#include <linux/smp.h>
#include <asm/cpu-info.h>
+#include <asm/cpu-type.h>
#include "op_impl.h"
@@ -85,6 +86,11 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_34K:
case CPU_1004K:
case CPU_74K:
+ case CPU_1074K:
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ case CPU_P5600:
+ case CPU_M5150:
case CPU_LOONGSON1:
case CPU_SB1:
case CPU_SB1A:
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 3a2b6e9f25c..42821ae2d77 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -372,10 +372,27 @@ static int __init mipsxx_init(void)
op_model_mipsxx_ops.cpu_type = "mips/34K";
break;
+ case CPU_1074K:
case CPU_74K:
op_model_mipsxx_ops.cpu_type = "mips/74K";
break;
+ case CPU_INTERAPTIV:
+ op_model_mipsxx_ops.cpu_type = "mips/interAptiv";
+ break;
+
+ case CPU_PROAPTIV:
+ op_model_mipsxx_ops.cpu_type = "mips/proAptiv";
+ break;
+
+ case CPU_P5600:
+ op_model_mipsxx_ops.cpu_type = "mips/P5600";
+ break;
+
+ case CPU_M5150:
+ op_model_mipsxx_ops.cpu_type = "mips/M5150";
+ break;
+
case CPU_5KC:
op_model_mipsxx_ops.cpu_type = "mips/5K";
break;
diff --git a/arch/mips/paravirt/Kconfig b/arch/mips/paravirt/Kconfig
new file mode 100644
index 00000000000..ecae5861b60
--- /dev/null
+++ b/arch/mips/paravirt/Kconfig
@@ -0,0 +1,6 @@
+if MIPS_PARAVIRT
+
+config MIPS_PCI_VIRTIO
+ def_bool y
+
+endif # MIPS_PARAVIRT
diff --git a/arch/mips/paravirt/Makefile b/arch/mips/paravirt/Makefile
new file mode 100644
index 00000000000..5023af733a3
--- /dev/null
+++ b/arch/mips/paravirt/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for MIPS para-virtualized specific kernel interface routines
+# under Linux.
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2013 Cavium, Inc.
+#
+
+obj-y := setup.o serial.o paravirt-irq.o
+
+obj-$(CONFIG_SMP) += paravirt-smp.o
diff --git a/arch/mips/paravirt/Platform b/arch/mips/paravirt/Platform
new file mode 100644
index 00000000000..7e76ef25ea1
--- /dev/null
+++ b/arch/mips/paravirt/Platform
@@ -0,0 +1,8 @@
+#
+# Generic para-virtualized guest.
+#
+platform-$(CONFIG_MIPS_PARAVIRT) += paravirt/
+cflags-$(CONFIG_MIPS_PARAVIRT) += \
+ -I$(srctree)/arch/mips/include/asm/mach-paravirt
+
+load-$(CONFIG_MIPS_PARAVIRT) = 0xffffffff80010000
diff --git a/arch/mips/paravirt/paravirt-irq.c b/arch/mips/paravirt/paravirt-irq.c
new file mode 100644
index 00000000000..8987b06c9de
--- /dev/null
+++ b/arch/mips/paravirt/paravirt-irq.c
@@ -0,0 +1,368 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+
+#define MBOX_BITS_PER_CPU 2
+
+static int cpunum_for_cpu(int cpu)
+{
+#ifdef CONFIG_SMP
+ return cpu_logical_map(cpu);
+#else
+ return get_ebase_cpunum();
+#endif
+}
+
+struct core_chip_data {
+ struct mutex core_irq_mutex;
+ bool current_en;
+ bool desired_en;
+ u8 bit;
+};
+
+static struct core_chip_data irq_core_chip_data[8];
+
+static void irq_core_ack(struct irq_data *data)
+{
+ struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
+ unsigned int bit = cd->bit;
+
+ /*
+ * We don't need to disable IRQs to make these atomic since
+ * they are already disabled earlier in the low level
+ * interrupt code.
+ */
+ clear_c0_status(0x100 << bit);
+ /* The two user interrupts must be cleared manually. */
+ if (bit < 2)
+ clear_c0_cause(0x100 << bit);
+}
+
+static void irq_core_eoi(struct irq_data *data)
+{
+ struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
+
+ /*
+ * We don't need to disable IRQs to make these atomic since
+ * they are already disabled earlier in the low level
+ * interrupt code.
+ */
+ set_c0_status(0x100 << cd->bit);
+}
+
+static void irq_core_set_enable_local(void *arg)
+{
+ struct irq_data *data = arg;
+ struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
+ unsigned int mask = 0x100 << cd->bit;
+
+ /*
+ * Interrupts are already disabled, so these are atomic.
+ */
+ if (cd->desired_en)
+ set_c0_status(mask);
+ else
+ clear_c0_status(mask);
+
+}
+
+static void irq_core_disable(struct irq_data *data)
+{
+ struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
+ cd->desired_en = false;
+}
+
+static void irq_core_enable(struct irq_data *data)
+{
+ struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
+ cd->desired_en = true;
+}
+
+static void irq_core_bus_lock(struct irq_data *data)
+{
+ struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&cd->core_irq_mutex);
+}
+
+static void irq_core_bus_sync_unlock(struct irq_data *data)
+{
+ struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
+
+ if (cd->desired_en != cd->current_en) {
+ on_each_cpu(irq_core_set_enable_local, data, 1);
+ cd->current_en = cd->desired_en;
+ }
+
+ mutex_unlock(&cd->core_irq_mutex);
+}
+
+static struct irq_chip irq_chip_core = {
+ .name = "Core",
+ .irq_enable = irq_core_enable,
+ .irq_disable = irq_core_disable,
+ .irq_ack = irq_core_ack,
+ .irq_eoi = irq_core_eoi,
+ .irq_bus_lock = irq_core_bus_lock,
+ .irq_bus_sync_unlock = irq_core_bus_sync_unlock,
+
+ .irq_cpu_online = irq_core_eoi,
+ .irq_cpu_offline = irq_core_ack,
+ .flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
+
+static void __init irq_init_core(void)
+{
+ int i;
+ int irq;
+ struct core_chip_data *cd;
+
+ /* Start with a clean slate */
+ clear_c0_status(ST0_IM);
+ clear_c0_cause(CAUSEF_IP0 | CAUSEF_IP1);
+
+ for (i = 0; i < ARRAY_SIZE(irq_core_chip_data); i++) {
+ cd = irq_core_chip_data + i;
+ cd->current_en = false;
+ cd->desired_en = false;
+ cd->bit = i;
+ mutex_init(&cd->core_irq_mutex);
+
+ irq = MIPS_CPU_IRQ_BASE + i;
+
+ switch (i) {
+ case 0: /* SW0 */
+ case 1: /* SW1 */
+ case 5: /* IP5 */
+ case 6: /* IP6 */
+ case 7: /* IP7 */
+ irq_set_chip_data(irq, cd);
+ irq_set_chip_and_handler(irq, &irq_chip_core,
+ handle_percpu_irq);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void __iomem *mips_irq_chip;
+#define MIPS_IRQ_CHIP_NUM_BITS 0
+#define MIPS_IRQ_CHIP_REGS 8
+
+static int mips_irq_cpu_stride;
+static int mips_irq_chip_reg_raw;
+static int mips_irq_chip_reg_src;
+static int mips_irq_chip_reg_en;
+static int mips_irq_chip_reg_raw_w1s;
+static int mips_irq_chip_reg_raw_w1c;
+static int mips_irq_chip_reg_en_w1s;
+static int mips_irq_chip_reg_en_w1c;
+
+static void irq_pci_enable(struct irq_data *data)
+{
+ u32 mask = 1u << data->irq;
+
+ __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s);
+}
+
+static void irq_pci_disable(struct irq_data *data)
+{
+ u32 mask = 1u << data->irq;
+
+ __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c);
+}
+
+static void irq_pci_ack(struct irq_data *data)
+{
+}
+
+static void irq_pci_mask(struct irq_data *data)
+{
+ u32 mask = 1u << data->irq;
+
+ __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c);
+}
+
+static void irq_pci_unmask(struct irq_data *data)
+{
+ u32 mask = 1u << data->irq;
+
+ __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s);
+}
+
+static struct irq_chip irq_chip_pci = {
+ .name = "PCI",
+ .irq_enable = irq_pci_enable,
+ .irq_disable = irq_pci_disable,
+ .irq_ack = irq_pci_ack,
+ .irq_mask = irq_pci_mask,
+ .irq_unmask = irq_pci_unmask,
+};
+
+static void irq_mbox_all(struct irq_data *data, void __iomem *base)
+{
+ int cpu;
+ unsigned int mbox = data->irq - MIPS_IRQ_MBOX0;
+ u32 mask;
+
+ WARN_ON(mbox >= MBOX_BITS_PER_CPU);
+
+ for_each_online_cpu(cpu) {
+ unsigned int cpuid = cpunum_for_cpu(cpu);
+ mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox);
+ __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride));
+ }
+}
+
+static void irq_mbox_enable(struct irq_data *data)
+{
+ irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32));
+}
+
+static void irq_mbox_disable(struct irq_data *data)
+{
+ irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32));
+}
+
+static void irq_mbox_ack(struct irq_data *data)
+{
+ u32 mask;
+ unsigned int mbox = data->irq - MIPS_IRQ_MBOX0;
+
+ WARN_ON(mbox >= MBOX_BITS_PER_CPU);
+
+ mask = 1 << (get_ebase_cpunum() * MBOX_BITS_PER_CPU + mbox);
+ __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1c + sizeof(u32));
+}
+
+void irq_mbox_ipi(int cpu, unsigned int actions)
+{
+ unsigned int cpuid = cpunum_for_cpu(cpu);
+ u32 mask;
+
+ WARN_ON(actions >= (1 << MBOX_BITS_PER_CPU));
+
+ mask = actions << (cpuid * MBOX_BITS_PER_CPU);
+ __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1s + sizeof(u32));
+}
+
+static void irq_mbox_cpu_onoffline(struct irq_data *data, void __iomem *base)
+{
+ unsigned int mbox = data->irq - MIPS_IRQ_MBOX0;
+ unsigned int cpuid = get_ebase_cpunum();
+ u32 mask;
+
+ WARN_ON(mbox >= MBOX_BITS_PER_CPU);
+
+ mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox);
+ __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride));
+
+}
+
+static void irq_mbox_cpu_online(struct irq_data *data)
+{
+ irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32));
+}
+
+static void irq_mbox_cpu_offline(struct irq_data *data)
+{
+ irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32));
+}
+
+static struct irq_chip irq_chip_mbox = {
+ .name = "MBOX",
+ .irq_enable = irq_mbox_enable,
+ .irq_disable = irq_mbox_disable,
+ .irq_ack = irq_mbox_ack,
+ .irq_cpu_online = irq_mbox_cpu_online,
+ .irq_cpu_offline = irq_mbox_cpu_offline,
+ .flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
+
+static void __init irq_pci_init(void)
+{
+ int i, stride;
+ u32 num_bits;
+
+ mips_irq_chip = ioremap(0x1e010000, 4096);
+
+ num_bits = __raw_readl(mips_irq_chip + MIPS_IRQ_CHIP_NUM_BITS);
+ stride = 8 * (1 + ((num_bits - 1) / 64));
+
+
+ pr_notice("mips_irq_chip: %u bits, reg stride: %d\n", num_bits, stride);
+ mips_irq_chip_reg_raw = MIPS_IRQ_CHIP_REGS + 0 * stride;
+ mips_irq_chip_reg_raw_w1s = MIPS_IRQ_CHIP_REGS + 1 * stride;
+ mips_irq_chip_reg_raw_w1c = MIPS_IRQ_CHIP_REGS + 2 * stride;
+ mips_irq_chip_reg_src = MIPS_IRQ_CHIP_REGS + 3 * stride;
+ mips_irq_chip_reg_en = MIPS_IRQ_CHIP_REGS + 4 * stride;
+ mips_irq_chip_reg_en_w1s = MIPS_IRQ_CHIP_REGS + 5 * stride;
+ mips_irq_chip_reg_en_w1c = MIPS_IRQ_CHIP_REGS + 6 * stride;
+ mips_irq_cpu_stride = stride * 4;
+
+ for (i = 0; i < 4; i++)
+ irq_set_chip_and_handler(i + MIPS_IRQ_PCIA, &irq_chip_pci, handle_level_irq);
+
+ for (i = 0; i < 2; i++)
+ irq_set_chip_and_handler(i + MIPS_IRQ_MBOX0, &irq_chip_mbox, handle_percpu_irq);
+
+
+ set_c0_status(STATUSF_IP2);
+}
+
+static void irq_pci_dispatch(void)
+{
+ unsigned int cpuid = get_ebase_cpunum();
+ u32 en;
+
+ en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src +
+ (cpuid * mips_irq_cpu_stride));
+
+ if (!en) {
+ en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src + (cpuid * mips_irq_cpu_stride) + sizeof(u32));
+ en = (en >> (2 * cpuid)) & 3;
+
+ if (!en)
+ spurious_interrupt();
+ else
+ do_IRQ(__ffs(en) + MIPS_IRQ_MBOX0); /* MBOX type */
+ } else {
+ do_IRQ(__ffs(en));
+ }
+}
+
+
+void __init arch_init_irq(void)
+{
+ irq_init_core();
+ irq_pci_init();
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int ip;
+
+ if (unlikely(!pending)) {
+ spurious_interrupt();
+ return;
+ }
+
+ ip = ffs(pending) - 1 - STATUSB_IP0;
+ if (ip == 2)
+ irq_pci_dispatch();
+ else
+ do_IRQ(MIPS_CPU_IRQ_BASE + ip);
+}
diff --git a/arch/mips/paravirt/paravirt-smp.c b/arch/mips/paravirt/paravirt-smp.c
new file mode 100644
index 00000000000..0164b0c4835
--- /dev/null
+++ b/arch/mips/paravirt/paravirt-smp.c
@@ -0,0 +1,143 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/mipsregs.h>
+#include <asm/setup.h>
+#include <asm/time.h>
+#include <asm/smp.h>
+
+/*
+ * Writing the sp releases the CPU, so writes must be ordered, gp
+ * first, then sp.
+ */
+unsigned long paravirt_smp_sp[NR_CPUS];
+unsigned long paravirt_smp_gp[NR_CPUS];
+
+static int numcpus = 1;
+
+static int __init set_numcpus(char *str)
+{
+ int newval;
+
+ if (get_option(&str, &newval)) {
+ if (newval < 1 || newval >= NR_CPUS)
+ goto bad;
+ numcpus = newval;
+ return 0;
+ }
+bad:
+ return -EINVAL;
+}
+early_param("numcpus", set_numcpus);
+
+
+static void paravirt_smp_setup(void)
+{
+ int id;
+ unsigned int cpunum = get_ebase_cpunum();
+
+ if (WARN_ON(cpunum >= NR_CPUS))
+ return;
+
+ /* The present CPUs are initially just the boot cpu (CPU 0). */
+ for (id = 0; id < NR_CPUS; id++) {
+ set_cpu_possible(id, id == 0);
+ set_cpu_present(id, id == 0);
+ }
+ __cpu_number_map[cpunum] = 0;
+ __cpu_logical_map[0] = cpunum;
+
+ for (id = 0; id < numcpus; id++) {
+ set_cpu_possible(id, true);
+ set_cpu_present(id, true);
+ __cpu_number_map[id] = id;
+ __cpu_logical_map[id] = id;
+ }
+}
+
+void irq_mbox_ipi(int cpu, unsigned int actions);
+static void paravirt_send_ipi_single(int cpu, unsigned int action)
+{
+ irq_mbox_ipi(cpu, action);
+}
+
+static void paravirt_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+ unsigned int cpu;
+
+ for_each_cpu_mask(cpu, *mask)
+ paravirt_send_ipi_single(cpu, action);
+}
+
+static void paravirt_init_secondary(void)
+{
+ unsigned int sr;
+
+ sr = set_c0_status(ST0_BEV);
+ write_c0_ebase((u32)ebase);
+
+ sr |= STATUSF_IP2; /* Interrupt controller on IP2 */
+ write_c0_status(sr);
+
+ irq_cpu_online();
+}
+
+static void paravirt_smp_finish(void)
+{
+ /* to generate the first CPU timer interrupt */
+ write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
+ local_irq_enable();
+}
+
+static void paravirt_boot_secondary(int cpu, struct task_struct *idle)
+{
+ paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle);
+ smp_wmb();
+ paravirt_smp_sp[cpu] = __KSTK_TOS(idle);
+}
+
+static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id)
+{
+ scheduler_ipi();
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t paravirt_function_interrupt(int irq, void *dev_id)
+{
+ smp_call_function_interrupt();
+ return IRQ_HANDLED;
+}
+
+static void paravirt_prepare_cpus(unsigned int max_cpus)
+{
+ if (request_irq(MIPS_IRQ_MBOX0, paravirt_reched_interrupt,
+ IRQF_PERCPU | IRQF_NO_THREAD, "Scheduler",
+ paravirt_reched_interrupt)) {
+ panic("Cannot request_irq for SchedulerIPI");
+ }
+ if (request_irq(MIPS_IRQ_MBOX1, paravirt_function_interrupt,
+ IRQF_PERCPU | IRQF_NO_THREAD, "SMP-Call",
+ paravirt_function_interrupt)) {
+ panic("Cannot request_irq for SMP-Call");
+ }
+}
+
+struct plat_smp_ops paravirt_smp_ops = {
+ .send_ipi_single = paravirt_send_ipi_single,
+ .send_ipi_mask = paravirt_send_ipi_mask,
+ .init_secondary = paravirt_init_secondary,
+ .smp_finish = paravirt_smp_finish,
+ .boot_secondary = paravirt_boot_secondary,
+ .smp_setup = paravirt_smp_setup,
+ .prepare_cpus = paravirt_prepare_cpus,
+};
diff --git a/arch/mips/paravirt/serial.c b/arch/mips/paravirt/serial.c
new file mode 100644
index 00000000000..02b665c0227
--- /dev/null
+++ b/arch/mips/paravirt/serial.c
@@ -0,0 +1,40 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/virtio_console.h>
+#include <linux/kvm_para.h>
+
+/*
+ * Emit one character to the boot console.
+ */
+int prom_putchar(char c)
+{
+ kvm_hypercall3(KVM_HC_MIPS_CONSOLE_OUTPUT, 0 /* port 0 */,
+ (unsigned long)&c, 1 /* len == 1 */);
+
+ return 1;
+}
+
+#ifdef CONFIG_VIRTIO_CONSOLE
+static int paravirt_put_chars(u32 vtermno, const char *buf, int count)
+{
+ kvm_hypercall3(KVM_HC_MIPS_CONSOLE_OUTPUT, vtermno,
+ (unsigned long)buf, count);
+
+ return count;
+}
+
+static int __init paravirt_cons_init(void)
+{
+ virtio_cons_early_init(paravirt_put_chars);
+ return 0;
+}
+core_initcall(paravirt_cons_init);
+
+#endif
diff --git a/arch/mips/paravirt/setup.c b/arch/mips/paravirt/setup.c
new file mode 100644
index 00000000000..cb8448b373a
--- /dev/null
+++ b/arch/mips/paravirt/setup.c
@@ -0,0 +1,67 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kvm_para.h>
+
+#include <asm/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/smp-ops.h>
+#include <asm/time.h>
+
+extern struct plat_smp_ops paravirt_smp_ops;
+
+const char *get_system_type(void)
+{
+ return "MIPS Para-Virtualized Guest";
+}
+
+void __init plat_time_init(void)
+{
+ mips_hpt_frequency = kvm_hypercall0(KVM_HC_MIPS_GET_CLOCK_FREQ);
+
+ preset_lpj = mips_hpt_frequency / (2 * HZ);
+}
+
+static void pv_machine_halt(void)
+{
+ kvm_hypercall0(KVM_HC_MIPS_EXIT_VM);
+}
+
+/*
+ * Early entry point for arch setup
+ */
+void __init prom_init(void)
+{
+ int i;
+ int argc = fw_arg0;
+ char **argv = (char **)fw_arg1;
+
+#ifdef CONFIG_32BIT
+ set_io_port_base(KSEG1ADDR(0x1e000000));
+#else /* CONFIG_64BIT */
+ set_io_port_base(PHYS_TO_XKSEG_UNCACHED(0x1e000000));
+#endif
+
+ for (i = 0; i < argc; i++) {
+ strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE);
+ if (i < argc - 1)
+ strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
+ }
+ _machine_halt = pv_machine_halt;
+ register_smp_ops(&paravirt_smp_ops);
+}
+
+void __init plat_mem_setup(void)
+{
+ /* Do nothing, the "mem=???" parser handles our memory. */
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 719e4557e22..ff8a5539b36 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \
obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o
obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o
obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o
-
+obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
#
# These are still pretty much in the old state, watch, go blind.
#
@@ -29,6 +29,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o
+obj-$(CONFIG_LEMOTE_MACH3A) += fixup-loongson3.o ops-loongson3.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o
obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
@@ -60,4 +61,5 @@ obj-$(CONFIG_CPU_XLP) += pci-xlp.o
ifdef CONFIG_PCI_MSI
obj-$(CONFIG_CAVIUM_OCTEON_SOC) += msi-octeon.o
+obj-$(CONFIG_CPU_XLP) += msi-xlp.o
endif
diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c
index 6c829df28dc..c2ce41ea61d 100644
--- a/arch/mips/pci/fixup-lantiq.c
+++ b/arch/mips/pci/fixup-lantiq.c
@@ -25,16 +25,5 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
- struct of_irq dev_irq;
- int irq;
-
- if (of_irq_map_pci(dev, &dev_irq)) {
- dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n",
- slot, pin);
- return 0;
- }
- irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier,
- dev_irq.size);
- dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq);
- return irq;
+ return of_irq_parse_and_map_pci(dev, slot, pin);
}
diff --git a/arch/mips/pci/fixup-loongson3.c b/arch/mips/pci/fixup-loongson3.c
new file mode 100644
index 00000000000..d708ae46d32
--- /dev/null
+++ b/arch/mips/pci/fixup-loongson3.c
@@ -0,0 +1,66 @@
+/*
+ * fixup-loongson3.c
+ *
+ * Copyright (C) 2012 Lemote, Inc.
+ * Author: Xiang Yu, xiangy@lemote.com
+ * Chen Huacai, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/pci.h>
+#include <boot_param.h>
+
+static void print_fixup_info(const struct pci_dev *pdev)
+{
+ dev_info(&pdev->dev, "Device %x:%x, irq %d\n",
+ pdev->vendor, pdev->device, pdev->irq);
+}
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ print_fixup_info(dev);
+ return dev->irq;
+}
+
+static void pci_fixup_radeon(struct pci_dev *pdev)
+{
+ if (pdev->resource[PCI_ROM_RESOURCE].start)
+ return;
+
+ if (!loongson_sysconf.vgabios_addr)
+ return;
+
+ pdev->resource[PCI_ROM_RESOURCE].start =
+ loongson_sysconf.vgabios_addr;
+ pdev->resource[PCI_ROM_RESOURCE].end =
+ loongson_sysconf.vgabios_addr + 256*1024 - 1;
+ pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY;
+
+ dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n",
+ PCI_ROM_RESOURCE, &pdev->resource[PCI_ROM_RESOURCE]);
+}
+
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
+ PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_radeon);
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index 07ada7f8441..40e920c653c 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -1,5 +1,6 @@
#include <linux/init.h>
#include <linux/pci.h>
+#include <asm/mips-boards/piix4.h>
/* PCI interrupt pins */
#define PCIA 1
@@ -50,10 +51,26 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
return 0;
}
+static void malta_piix_func3_base_fixup(struct pci_dev *dev)
+{
+ /* Set a sane PM I/O base address */
+ pci_write_config_word(dev, PIIX4_FUNC3_PMBA, 0x1000);
+
+ /* Enable access to the PM I/O region */
+ pci_write_config_byte(dev, PIIX4_FUNC3_PMREGMISC,
+ PIIX4_FUNC3_PMREGMISC_EN);
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+ malta_piix_func3_base_fixup);
+
static void malta_piix_func0_fixup(struct pci_dev *pdev)
{
unsigned char reg_val;
- static int piixirqmap[16] = { /* PIIX PIRQC[A:D] irq mappings */
+ u32 reg_val32;
+ u16 reg_val16;
+ /* PIIX PIRQC[A:D] irq mappings */
+ static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = {
0, 0, 0, 3,
4, 5, 6, 7,
0, 9, 10, 11,
@@ -63,11 +80,12 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev)
/* Interrogate PIIX4 to get PCI IRQ mapping */
for (i = 0; i <= 3; i++) {
- pci_read_config_byte(pdev, 0x60+i, &reg_val);
- if (reg_val & 0x80)
+ pci_read_config_byte(pdev, PIIX4_FUNC0_PIRQRC+i, &reg_val);
+ if (reg_val & PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_DISABLE)
pci_irq[PCIA+i] = 0; /* Disabled */
else
- pci_irq[PCIA+i] = piixirqmap[reg_val & 15];
+ pci_irq[PCIA+i] = piixirqmap[reg_val &
+ PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MASK];
}
/* Done by YAMON 2.00 onwards */
@@ -76,9 +94,25 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev)
* Set top of main memory accessible by ISA or DMA
* devices to 16 Mb.
*/
- pci_read_config_byte(pdev, 0x69, &reg_val);
- pci_write_config_byte(pdev, 0x69, reg_val | 0xf0);
+ pci_read_config_byte(pdev, PIIX4_FUNC0_TOM, &reg_val);
+ pci_write_config_byte(pdev, PIIX4_FUNC0_TOM, reg_val |
+ PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK);
}
+
+ /* Mux SERIRQ to its pin */
+ pci_read_config_dword(pdev, PIIX4_FUNC0_GENCFG, &reg_val32);
+ pci_write_config_dword(pdev, PIIX4_FUNC0_GENCFG,
+ reg_val32 | PIIX4_FUNC0_GENCFG_SERIRQ);
+
+ /* Enable SERIRQ */
+ pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, &reg_val);
+ reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT;
+ pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val);
+
+ /* Enable response to special cycles */
+ pci_read_config_word(pdev, PCI_COMMAND, &reg_val16);
+ pci_write_config_word(pdev, PCI_COMMAND,
+ reg_val16 | PCI_COMMAND_SPECIAL);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
@@ -93,10 +127,14 @@ static void malta_piix_func1_fixup(struct pci_dev *pdev)
/*
* IDE Decode enable.
*/
- pci_read_config_byte(pdev, 0x41, &reg_val);
- pci_write_config_byte(pdev, 0x41, reg_val|0x80);
- pci_read_config_byte(pdev, 0x43, &reg_val);
- pci_write_config_byte(pdev, 0x43, reg_val|0x80);
+ pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI,
+ &reg_val);
+ pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI,
+ reg_val|PIIX4_FUNC1_IDETIM_PRIMARY_HI_IDE_DECODE_EN);
+ pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI,
+ &reg_val);
+ pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI,
+ reg_val|PIIX4_FUNC1_IDETIM_SECONDARY_HI_IDE_DECODE_EN);
}
}
@@ -108,10 +146,12 @@ static void quirk_dlcsetup(struct pci_dev *dev)
{
u8 odlc, ndlc;
- (void) pci_read_config_byte(dev, 0x82, &odlc);
+ (void) pci_read_config_byte(dev, PIIX4_FUNC0_DLC, &odlc);
/* Enable passive releases and delayed transaction */
- ndlc = odlc | 7;
- (void) pci_write_config_byte(dev, 0x82, ndlc);
+ ndlc = odlc | PIIX4_FUNC0_DLC_USBPR_EN |
+ PIIX4_FUNC0_DLC_PASSIVE_RELEASE_EN |
+ PIIX4_FUNC0_DLC_DELAYED_TRANSACTION_EN;
+ (void) pci_write_config_byte(dev, PIIX4_FUNC0_DLC, ndlc);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
diff --git a/arch/mips/pci/fixup-rc32434.c b/arch/mips/pci/fixup-rc32434.c
index d0f6ecbf35f..7fcafd5da7d 100644
--- a/arch/mips/pci/fixup-rc32434.c
+++ b/arch/mips/pci/fixup-rc32434.c
@@ -27,7 +27,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <asm/mach-rc32434/rc32434.h>
#include <asm/mach-rc32434/irq.h>
diff --git a/arch/mips/pci/fixup-sb1250.c b/arch/mips/pci/fixup-sb1250.c
index 1441becdcb6..8feae9154ba 100644
--- a/arch/mips/pci/fixup-sb1250.c
+++ b/arch/mips/pci/fixup-sb1250.c
@@ -8,7 +8,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/init.h>
#include <linux/pci.h>
/*
diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c
index d37be36dc65..ab0c5d14c6f 100644
--- a/arch/mips/pci/msi-octeon.c
+++ b/arch/mips/pci/msi-octeon.c
@@ -15,6 +15,7 @@
#include <asm/octeon/cvmx-npi-defs.h>
#include <asm/octeon/cvmx-pci-defs.h>
#include <asm/octeon/cvmx-npei-defs.h>
+#include <asm/octeon/cvmx-sli-defs.h>
#include <asm/octeon/cvmx-pexp-defs.h>
#include <asm/octeon/pci-octeon.h>
@@ -150,6 +151,7 @@ msi_irq_allocated:
msg.address_lo =
((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff;
msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32;
+ break;
case OCTEON_DMA_BAR_TYPE_BIG:
/* When using big bar, Bar 0 is based at 0 */
msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff;
@@ -161,6 +163,11 @@ msi_irq_allocated:
msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff;
msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32;
break;
+ case OCTEON_DMA_BAR_TYPE_PCIE2:
+ /* When using PCIe2, Bar 0 is based at 0 */
+ msg.address_lo = (0 + CVMX_SLI_PCIE_MSI_RCV) & 0xffffffff;
+ msg.address_hi = (0 + CVMX_SLI_PCIE_MSI_RCV) >> 32;
+ break;
default:
panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type");
}
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
new file mode 100644
index 00000000000..fa374fe3746
--- /dev/null
+++ b/arch/mips/pci/msi-xlp.c
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the Broadcom
+ * license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/msi.h>
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+
+#include <asm/netlogic/interrupt.h>
+#include <asm/netlogic/haldefs.h>
+#include <asm/netlogic/common.h>
+#include <asm/netlogic/mips-extns.h>
+
+#include <asm/netlogic/xlp-hal/iomap.h>
+#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/pic.h>
+#include <asm/netlogic/xlp-hal/pcibus.h>
+#include <asm/netlogic/xlp-hal/bridge.h>
+
+#define XLP_MSIVEC_PER_LINK 32
+#define XLP_MSIXVEC_TOTAL (cpu_is_xlp9xx() ? 128 : 32)
+#define XLP_MSIXVEC_PER_LINK (cpu_is_xlp9xx() ? 32 : 8)
+
+/* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */
+static inline int nlm_link_msiirq(int link, int msivec)
+{
+ return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec;
+}
+
+/* get the link MSI vector from irq number */
+static inline int nlm_irq_msivec(int irq)
+{
+ return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK;
+}
+
+/* get the link from the irq number */
+static inline int nlm_irq_msilink(int irq)
+{
+ int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS;
+
+ return ((irq - NLM_MSI_VEC_BASE) % total_msivec) /
+ XLP_MSIVEC_PER_LINK;
+}
+
+/*
+ * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because
+ * there are only 32 PIC interrupts for MSI. We split them statically
+ * and use 8 MSI-X vectors per link - this keeps the allocation and
+ * lookup simple.
+ * On XLP 9xx, there are 32 vectors per link, and the interrupts are
+ * not routed thru PIC, so we can use all 128 MSI-X vectors.
+ */
+static inline int nlm_link_msixirq(int link, int bit)
+{
+ return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit;
+}
+
+/* get the link MSI vector from irq number */
+static inline int nlm_irq_msixvec(int irq)
+{
+ return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL;
+}
+
+/* get the link from MSIX vec */
+static inline int nlm_irq_msixlink(int msixvec)
+{
+ return msixvec / XLP_MSIXVEC_PER_LINK;
+}
+
+/*
+ * Per link MSI and MSI-X information, set as IRQ handler data for
+ * MSI and MSI-X interrupts.
+ */
+struct xlp_msi_data {
+ struct nlm_soc_info *node;
+ uint64_t lnkbase;
+ uint32_t msi_enabled_mask;
+ uint32_t msi_alloc_mask;
+ uint32_t msix_alloc_mask;
+ spinlock_t msi_lock;
+};
+
+/*
+ * MSI Chip definitions
+ *
+ * On XLP, there is a PIC interrupt associated with each PCIe link on the
+ * chip (which appears as a PCI bridge to us). This gives us 32 MSI irqa
+ * per link and 128 overall.
+ *
+ * When a device connected to the link raises a MSI interrupt, we get a
+ * link interrupt and we then have to look at PCIE_MSI_STATUS register at
+ * the bridge to map it to the IRQ
+ */
+static void xlp_msi_enable(struct irq_data *d)
+{
+ struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+ unsigned long flags;
+ int vec;
+
+ vec = nlm_irq_msivec(d->irq);
+ spin_lock_irqsave(&md->msi_lock, flags);
+ md->msi_enabled_mask |= 1u << vec;
+ if (cpu_is_xlp9xx())
+ nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+ md->msi_enabled_mask);
+ else
+ nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+ spin_unlock_irqrestore(&md->msi_lock, flags);
+}
+
+static void xlp_msi_disable(struct irq_data *d)
+{
+ struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+ unsigned long flags;
+ int vec;
+
+ vec = nlm_irq_msivec(d->irq);
+ spin_lock_irqsave(&md->msi_lock, flags);
+ md->msi_enabled_mask &= ~(1u << vec);
+ if (cpu_is_xlp9xx())
+ nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN,
+ md->msi_enabled_mask);
+ else
+ nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask);
+ spin_unlock_irqrestore(&md->msi_lock, flags);
+}
+
+static void xlp_msi_mask_ack(struct irq_data *d)
+{
+ struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+ int link, vec;
+
+ link = nlm_irq_msilink(d->irq);
+ vec = nlm_irq_msivec(d->irq);
+ xlp_msi_disable(d);
+
+ /* Ack MSI on bridge */
+ if (cpu_is_xlp9xx())
+ nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec);
+ else
+ nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec);
+
+ /* Ack at eirr and PIC */
+ ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link));
+ if (cpu_is_xlp9xx())
+ nlm_pic_ack(md->node->picbase,
+ PIC_9XX_IRT_PCIE_LINK_INDEX(link));
+ else
+ nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link));
+}
+
+static struct irq_chip xlp_msi_chip = {
+ .name = "XLP-MSI",
+ .irq_enable = xlp_msi_enable,
+ .irq_disable = xlp_msi_disable,
+ .irq_mask_ack = xlp_msi_mask_ack,
+ .irq_unmask = xlp_msi_enable,
+};
+
+/*
+ * XLP8XX/4XX/3XX/2XX:
+ * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X
+ * interrupts generated by the PIC and each of these correspond to a MSI-X
+ * vector (0-31) that can be assigned.
+ *
+ * We divide the MSI-X vectors to 8 per link and do a per-link allocation
+ *
+ * XLP9XX:
+ * 32 MSI-X vectors are available per link, and the interrupts are not routed
+ * thru the PIC. PIC ack not needed.
+ *
+ * Enable and disable done using standard MSI functions.
+ */
+static void xlp_msix_mask_ack(struct irq_data *d)
+{
+ struct xlp_msi_data *md;
+ int link, msixvec;
+ uint32_t status_reg, bit;
+
+ msixvec = nlm_irq_msixvec(d->irq);
+ link = nlm_irq_msixlink(msixvec);
+ mask_msi_irq(d);
+ md = irq_data_get_irq_handler_data(d);
+
+ /* Ack MSI on bridge */
+ if (cpu_is_xlp9xx()) {
+ status_reg = PCIE_9XX_MSIX_STATUSX(link);
+ bit = msixvec % XLP_MSIXVEC_PER_LINK;
+ } else {
+ status_reg = PCIE_MSIX_STATUS;
+ bit = msixvec;
+ }
+ nlm_write_reg(md->lnkbase, status_reg, 1u << bit);
+
+ /* Ack at eirr and PIC */
+ ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link));
+ if (!cpu_is_xlp9xx())
+ nlm_pic_ack(md->node->picbase,
+ PIC_IRT_PCIE_MSIX_INDEX(msixvec));
+}
+
+static struct irq_chip xlp_msix_chip = {
+ .name = "XLP-MSIX",
+ .irq_enable = unmask_msi_irq,
+ .irq_disable = mask_msi_irq,
+ .irq_mask_ack = xlp_msix_mask_ack,
+ .irq_unmask = unmask_msi_irq,
+};
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+}
+
+/*
+ * Setup a PCIe link for MSI. By default, the links are in
+ * legacy interrupt mode. We will switch them to MSI mode
+ * at the first MSI request.
+ */
+static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr)
+{
+ u32 val;
+
+ if (cpu_is_xlp9xx()) {
+ val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+ if ((val & 0x200) == 0) {
+ val |= 0x200; /* MSI Interrupt enable */
+ nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+ }
+ } else {
+ val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+ if ((val & 0x200) == 0) {
+ val |= 0x200;
+ nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+ }
+ }
+
+ val = nlm_read_reg(lnkbase, 0x1); /* CMD */
+ if ((val & 0x0400) == 0) {
+ val |= 0x0400;
+ nlm_write_reg(lnkbase, 0x1, val);
+ }
+
+ /* Update IRQ in the PCI irq reg */
+ val = nlm_read_pci_reg(lnkbase, 0xf);
+ val &= ~0x1fu;
+ val |= (1 << 8) | lirq;
+ nlm_write_pci_reg(lnkbase, 0xf, val);
+
+ /* MSI addr */
+ nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_ADDRH, msiaddr >> 32);
+ nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_ADDRL, msiaddr & 0xffffffff);
+
+ /* MSI cap for bridge */
+ val = nlm_read_reg(lnkbase, PCIE_BRIDGE_MSI_CAP);
+ if ((val & (1 << 16)) == 0) {
+ val |= 0xb << 16; /* mmc32, msi enable */
+ nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_CAP, val);
+ }
+}
+
+/*
+ * Allocate a MSI vector on a link
+ */
+static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
+ struct msi_desc *desc)
+{
+ struct xlp_msi_data *md;
+ struct msi_msg msg;
+ unsigned long flags;
+ int msivec, irt, lirq, xirq, ret;
+ uint64_t msiaddr;
+
+ /* Get MSI data for the link */
+ lirq = PIC_PCIE_LINK_MSI_IRQ(link);
+ xirq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
+ md = irq_get_handler_data(xirq);
+ msiaddr = MSI_LINK_ADDR(node, link);
+
+ spin_lock_irqsave(&md->msi_lock, flags);
+ if (md->msi_alloc_mask == 0) {
+ xlp_config_link_msi(lnkbase, lirq, msiaddr);
+ /* switch the link IRQ to MSI range */
+ if (cpu_is_xlp9xx())
+ irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
+ else
+ irt = PIC_IRT_PCIE_LINK_INDEX(link);
+ nlm_setup_pic_irq(node, lirq, lirq, irt);
+ nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
+ node * nlm_threads_per_node(), 1 /*en */);
+ }
+
+ /* allocate a MSI vec, and tell the bridge about it */
+ msivec = fls(md->msi_alloc_mask);
+ if (msivec == XLP_MSIVEC_PER_LINK) {
+ spin_unlock_irqrestore(&md->msi_lock, flags);
+ return -ENOMEM;
+ }
+ md->msi_alloc_mask |= (1u << msivec);
+ spin_unlock_irqrestore(&md->msi_lock, flags);
+
+ msg.address_hi = msiaddr >> 32;
+ msg.address_lo = msiaddr & 0xffffffff;
+ msg.data = 0xc00 | msivec;
+
+ xirq = xirq + msivec; /* msi mapped to global irq space */
+ ret = irq_set_msi_desc(xirq, desc);
+ if (ret < 0)
+ return ret;
+
+ write_msi_msg(xirq, &msg);
+ return 0;
+}
+
+/*
+ * Switch a link to MSI-X mode
+ */
+static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
+{
+ u32 val;
+
+ val = nlm_read_reg(lnkbase, 0x2C);
+ if ((val & 0x80000000U) == 0) {
+ val |= 0x80000000U;
+ nlm_write_reg(lnkbase, 0x2C, val);
+ }
+
+ if (cpu_is_xlp9xx()) {
+ val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
+ if ((val & 0x200) == 0) {
+ val |= 0x200; /* MSI Interrupt enable */
+ nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
+ }
+ } else {
+ val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
+ if ((val & 0x200) == 0) {
+ val |= 0x200; /* MSI Interrupt enable */
+ nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
+ }
+ }
+
+ val = nlm_read_reg(lnkbase, 0x1); /* CMD */
+ if ((val & 0x0400) == 0) {
+ val |= 0x0400;
+ nlm_write_reg(lnkbase, 0x1, val);
+ }
+
+ /* Update IRQ in the PCI irq reg */
+ val = nlm_read_pci_reg(lnkbase, 0xf);
+ val &= ~0x1fu;
+ val |= (1 << 8) | lirq;
+ nlm_write_pci_reg(lnkbase, 0xf, val);
+
+ if (cpu_is_xlp9xx()) {
+ /* MSI-X addresses */
+ nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE,
+ msixaddr >> 8);
+ nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT,
+ (msixaddr + MSI_ADDR_SZ) >> 8);
+ } else {
+ /* MSI-X addresses */
+ nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE,
+ msixaddr >> 8);
+ nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
+ (msixaddr + MSI_ADDR_SZ) >> 8);
+ }
+}
+
+/*
+ * Allocate a MSI-X vector
+ */
+static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
+ struct msi_desc *desc)
+{
+ struct xlp_msi_data *md;
+ struct msi_msg msg;
+ unsigned long flags;
+ int t, msixvec, lirq, xirq, ret;
+ uint64_t msixaddr;
+
+ /* Get MSI data for the link */
+ lirq = PIC_PCIE_MSIX_IRQ(link);
+ xirq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
+ md = irq_get_handler_data(xirq);
+ msixaddr = MSIX_LINK_ADDR(node, link);
+
+ spin_lock_irqsave(&md->msi_lock, flags);
+ /* switch the PCIe link to MSI-X mode at the first alloc */
+ if (md->msix_alloc_mask == 0)
+ xlp_config_link_msix(lnkbase, lirq, msixaddr);
+
+ /* allocate a MSI-X vec, and tell the bridge about it */
+ t = fls(md->msix_alloc_mask);
+ if (t == XLP_MSIXVEC_PER_LINK) {
+ spin_unlock_irqrestore(&md->msi_lock, flags);
+ return -ENOMEM;
+ }
+ md->msix_alloc_mask |= (1u << t);
+ spin_unlock_irqrestore(&md->msi_lock, flags);
+
+ xirq += t;
+ msixvec = nlm_irq_msixvec(xirq);
+
+ msg.address_hi = msixaddr >> 32;
+ msg.address_lo = msixaddr & 0xffffffff;
+ msg.data = 0xc00 | msixvec;
+
+ ret = irq_set_msi_desc(xirq, desc);
+ if (ret < 0) {
+ destroy_irq(xirq);
+ return ret;
+ }
+
+ write_msi_msg(xirq, &msg);
+ return 0;
+}
+
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+{
+ struct pci_dev *lnkdev;
+ uint64_t lnkbase;
+ int node, link, slot;
+
+ lnkdev = xlp_get_pcie_link(dev);
+ if (lnkdev == NULL) {
+ dev_err(&dev->dev, "Could not find bridge\n");
+ return 1;
+ }
+ slot = PCI_SLOT(lnkdev->devfn);
+ link = PCI_FUNC(lnkdev->devfn);
+ node = slot / 8;
+ lnkbase = nlm_get_pcie_base(node, link);
+
+ if (desc->msi_attrib.is_msix)
+ return xlp_setup_msix(lnkbase, node, link, desc);
+ else
+ return xlp_setup_msi(lnkbase, node, link, desc);
+}
+
+void __init xlp_init_node_msi_irqs(int node, int link)
+{
+ struct nlm_soc_info *nodep;
+ struct xlp_msi_data *md;
+ int irq, i, irt, msixvec, val;
+
+ pr_info("[%d %d] Init node PCI IRT\n", node, link);
+ nodep = nlm_get_node(node);
+
+ /* Alloc an MSI block for the link */
+ md = kzalloc(sizeof(*md), GFP_KERNEL);
+ spin_lock_init(&md->msi_lock);
+ md->msi_enabled_mask = 0;
+ md->msi_alloc_mask = 0;
+ md->msix_alloc_mask = 0;
+ md->node = nodep;
+ md->lnkbase = nlm_get_pcie_base(node, link);
+
+ /* extended space for MSI interrupts */
+ irq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
+ for (i = irq; i < irq + XLP_MSIVEC_PER_LINK; i++) {
+ irq_set_chip_and_handler(i, &xlp_msi_chip, handle_level_irq);
+ irq_set_handler_data(i, md);
+ }
+
+ for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
+ if (cpu_is_xlp9xx()) {
+ val = ((node * nlm_threads_per_node()) << 7 |
+ PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0);
+ nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i +
+ (link * XLP_MSIXVEC_PER_LINK)), val);
+ } else {
+ /* Initialize MSI-X irts to generate one interrupt
+ * per link
+ */
+ msixvec = link * XLP_MSIXVEC_PER_LINK + i;
+ irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
+ nlm_pic_init_irt(nodep->picbase, irt,
+ PIC_PCIE_MSIX_IRQ(link),
+ node * nlm_threads_per_node(), 1);
+ }
+
+ /* Initialize MSI-X extended irq space for the link */
+ irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
+ irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
+ irq_set_handler_data(irq, md);
+ }
+}
+
+void nlm_dispatch_msi(int node, int lirq)
+{
+ struct xlp_msi_data *md;
+ int link, i, irqbase;
+ u32 status;
+
+ link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE;
+ irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
+ md = irq_get_handler_data(irqbase);
+ if (cpu_is_xlp9xx())
+ status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) &
+ md->msi_enabled_mask;
+ else
+ status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
+ md->msi_enabled_mask;
+ while (status) {
+ i = __ffs(status);
+ do_IRQ(irqbase + i);
+ status &= status - 1;
+ }
+}
+
+void nlm_dispatch_msix(int node, int lirq)
+{
+ struct xlp_msi_data *md;
+ int link, i, irqbase;
+ u32 status;
+
+ link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
+ irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
+ md = irq_get_handler_data(irqbase);
+ if (cpu_is_xlp9xx())
+ status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
+ else
+ status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
+
+ /* narrow it down to the MSI-x vectors for our link */
+ if (!cpu_is_xlp9xx())
+ status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
+ ((1 << XLP_MSIXVEC_PER_LINK) - 1);
+
+ while (status) {
+ i = __ffs(status);
+ do_IRQ(irqbase + i);
+ status &= status - 1;
+ }
+}
diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c
index 6144bb337e4..13eea696bbe 100644
--- a/arch/mips/pci/ops-bcm63xx.c
+++ b/arch/mips/pci/ops-bcm63xx.c
@@ -9,7 +9,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/delay.h>
#include <linux/io.h>
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index 830352e3aed..c06205a8734 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -22,7 +22,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <asm/mips-boards/bonito64.h>
diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c
index 16e7c2526d7..e5738ee26f4 100644
--- a/arch/mips/pci/ops-lantiq.c
+++ b/arch/mips/pci/ops-lantiq.c
@@ -9,7 +9,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <asm/addrspace.h>
diff --git a/arch/mips/pci/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c
index 98254afa028..24138bb0cbe 100644
--- a/arch/mips/pci/ops-loongson2.c
+++ b/arch/mips/pci/ops-loongson2.c
@@ -14,7 +14,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/export.h>
#include <loongson.h>
diff --git a/arch/mips/pci/ops-loongson3.c b/arch/mips/pci/ops-loongson3.c
new file mode 100644
index 00000000000..46ed541a3ec
--- /dev/null
+++ b/arch/mips/pci/ops-loongson3.c
@@ -0,0 +1,101 @@
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+#include <loongson.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#define HT1LO_PCICFG_BASE 0x1a000000
+#define HT1LO_PCICFG_BASE_TP1 0x1b000000
+
+static int loongson3_pci_config_access(unsigned char access_type,
+ struct pci_bus *bus, unsigned int devfn,
+ int where, u32 *data)
+{
+ unsigned char busnum = bus->number;
+ u_int64_t addr, type;
+ void *addrp;
+ int device = PCI_SLOT(devfn);
+ int function = PCI_FUNC(devfn);
+ int reg = where & ~3;
+
+ addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+ if (busnum == 0) {
+ if (device > 31)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr & 0xffff));
+ type = 0;
+
+ } else {
+ addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr));
+ type = 0x10000;
+ }
+
+ if (access_type == PCI_ACCESS_WRITE)
+ writel(*data, addrp);
+ else {
+ *data = readl(addrp);
+ if (*data == 0xffffffff) {
+ *data = -1;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ u32 data = 0;
+ int ret = loongson3_pci_config_access(PCI_ACCESS_READ,
+ bus, devfn, where, &data);
+
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+ int ret;
+
+ if (size == 4)
+ data = val;
+ else {
+ ret = loongson3_pci_config_access(PCI_ACCESS_READ,
+ bus, devfn, where, &data);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ ret = loongson3_pci_config_access(PCI_ACCESS_WRITE,
+ bus, devfn, where, &data);
+
+ return ret;
+}
+
+struct pci_ops loongson_pci_ops = {
+ .read = loongson3_pci_pcibios_read,
+ .write = loongson3_pci_pcibios_write
+};
diff --git a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c
index 1cfb5588699..6b5821febc3 100644
--- a/arch/mips/pci/ops-mace.c
+++ b/arch/mips/pci/ops-mace.c
@@ -6,7 +6,6 @@
* Copyright (C) 2000, 2001 Keith M Wesolowski
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <asm/pci.h>
diff --git a/arch/mips/pci/ops-msc.c b/arch/mips/pci/ops-msc.c
index 92a8543361b..dbbf3657896 100644
--- a/arch/mips/pci/ops-msc.c
+++ b/arch/mips/pci/ops-msc.c
@@ -24,7 +24,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <asm/mips-boards/msc01_pci.h>
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
index 499e35c3eb3..a1a7c9f4096 100644
--- a/arch/mips/pci/ops-nile4.c
+++ b/arch/mips/pci/ops-nile4.c
@@ -1,5 +1,4 @@
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/pci.h>
#include <asm/bootinfo.h>
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
index 3d27800edba..50034f985be 100644
--- a/arch/mips/pci/ops-pmcmsp.c
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -7,7 +7,7 @@
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* Much of the code is derived from the original DDB5074 port by
- * Geert Uytterhoeven <geert@sonycom.com>
+ * Geert Uytterhoeven <geert@linux-m68k.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
diff --git a/arch/mips/pci/ops-rc32434.c b/arch/mips/pci/ops-rc32434.c
index 7c7182e2350..874ed6df976 100644
--- a/arch/mips/pci/ops-rc32434.c
+++ b/arch/mips/pci/ops-rc32434.c
@@ -26,7 +26,6 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/delay.h>
-#include <linux/init.h>
#include <linux/io.h>
#include <linux/pci.h>
#include <linux/types.h>
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c
index 02d64f77e96..d35dc9c9ab9 100644
--- a/arch/mips/pci/ops-tx3927.c
+++ b/arch/mips/pci/ops-tx3927.c
@@ -11,7 +11,7 @@
* Define the pci_ops for TX3927.
*
* Much of the code is derived from the original DDB5074 port by
- * Geert Uytterhoeven <geert@sonycom.com>
+ * Geert Uytterhoeven <geert@linux-m68k.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
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
index 3d5df514d02..0e046d82e4e 100644
--- a/arch/mips/pci/ops-tx4927.c
+++ b/arch/mips/pci/ops-tx4927.c
@@ -202,17 +202,20 @@ char *tx4927_pcibios_setup(char *str)
unsigned long val;
if (!strncmp(str, "trdyto=", 7)) {
- if (strict_strtoul(str + 7, 0, &val) == 0)
+ u8 val = 0;
+ if (kstrtou8(str + 7, 0, &val) == 0)
tx4927_pci_opts.trdyto = val;
return NULL;
}
if (!strncmp(str, "retryto=", 8)) {
- if (strict_strtoul(str + 8, 0, &val) == 0)
+ u8 val = 0;
+ if (kstrtou8(str + 8, 0, &val) == 0)
tx4927_pci_opts.retryto = val;
return NULL;
}
if (!strncmp(str, "gbwc=", 5)) {
- if (strict_strtoul(str + 5, 0, &val) == 0)
+ u16 val;
+ if (kstrtou16(str + 5, 0, &val) == 0)
tx4927_pci_opts.gbwc = val;
return NULL;
}
diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c
index d1faece21b6..563d1f61d6e 100644
--- a/arch/mips/pci/pci-alchemy.c
+++ b/arch/mips/pci/pci-alchemy.c
@@ -16,6 +16,7 @@
#include <linux/syscore_ops.h>
#include <linux/vmalloc.h>
+#include <asm/dma-coherence.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/tlbmisc.h>
@@ -411,17 +412,15 @@ static int alchemy_pci_probe(struct platform_device *pdev)
}
ctx->alchemy_pci_ctrl.io_map_base = (unsigned long)virt_io;
-#ifdef CONFIG_DMA_NONCOHERENT
/* Au1500 revisions older than AD have borked coherent PCI */
if ((alchemy_get_cputype() == ALCHEMY_CPU_AU1500) &&
- (read_c0_prid() < 0x01030202)) {
+ (read_c0_prid() < 0x01030202) && !coherentio) {
val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
val |= PCI_CONFIG_NC;
__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
wmb();
dev_info(&pdev->dev, "non-coherent PCI on Au1500 AA/AB/AC\n");
}
-#endif
if (pd->board_map_irq)
ctx->board_map_irq = pd->board_map_irq;
diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c
index 18517dd0f70..d471a26dd5f 100644
--- a/arch/mips/pci/pci-ar71xx.c
+++ b/arch/mips/pci/pci-ar71xx.c
@@ -363,9 +363,6 @@ static int ar71xx_pci_probe(struct platform_device *pdev)
spin_lock_init(&apc->lock);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
- if (!res)
- return -EINVAL;
-
apc->cfg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->cfg_base))
return PTR_ERR(apc->cfg_base);
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 65ec032fa0b..785b2659b51 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -362,25 +362,16 @@ static int ar724x_pci_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base");
- if (!res)
- return -EINVAL;
-
apc->ctrl_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->ctrl_base))
return PTR_ERR(apc->ctrl_base);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
- if (!res)
- return -EINVAL;
-
apc->devcfg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->devcfg_base))
return PTR_ERR(apc->devcfg_base);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base");
- if (!res)
- return -EINVAL;
-
apc->crp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->crp_base))
return PTR_ERR(apc->crp_base);
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c
index 44dd5aa2e36..5ec2a7bae02 100644
--- a/arch/mips/pci/pci-bcm1480.c
+++ b/arch/mips/pci/pci-bcm1480.c
@@ -39,6 +39,7 @@
#include <linux/mm.h>
#include <linux/console.h>
#include <linux/tty.h>
+#include <linux/vt.h>
#include <asm/sibyte/bcm1480_regs.h>
#include <asm/sibyte/bcm1480_scd.h>
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 162b4cb29db..0f09eafa5e3 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -7,7 +7,6 @@
* Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org)
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/pci.h>
diff --git a/arch/mips/pci/pci-malta.c b/arch/mips/pci/pci-malta.c
index 37134ddfeaa..cfbbc3e3e91 100644
--- a/arch/mips/pci/pci-malta.c
+++ b/arch/mips/pci/pci-malta.c
@@ -27,7 +27,7 @@
#include <linux/init.h>
#include <asm/gt64120.h>
-#include <asm/gcmpregs.h>
+#include <asm/mips-cm.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/bonito64.h>
#include <asm/mips-boards/msc01_pci.h>
@@ -201,11 +201,11 @@ void __init mips_pcibios_init(void)
msc_mem_resource.start = start & mask;
msc_mem_resource.end = (start & mask) | ~mask;
msc_controller.mem_offset = (start & mask) - (map & mask);
-#ifdef CONFIG_MIPS_CMP
- if (gcmp_niocu())
- gcmp_setregion(0, start, mask,
- GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
-#endif
+ if (mips_cm_numiocu()) {
+ write_gcr_reg0_base(start);
+ write_gcr_reg0_mask(mask |
+ CM_GCR_REGn_MASK_CMTGT_IOCU0);
+ }
MSC_READ(MSC01_PCI_SC2PIOBASL, start);
MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
@@ -213,11 +213,11 @@ void __init mips_pcibios_init(void)
msc_io_resource.end = (map & mask) | ~mask;
msc_controller.io_offset = 0;
ioport_resource.end = ~mask;
-#ifdef CONFIG_MIPS_CMP
- if (gcmp_niocu())
- gcmp_setregion(1, start, mask,
- GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
-#endif
+ if (mips_cm_numiocu()) {
+ write_gcr_reg1_base(start);
+ write_gcr_reg1_mask(mask |
+ CM_GCR_REGn_MASK_CMTGT_IOCU0);
+ }
/* If ranges overlap I/O takes precedence. */
start = start & mask;
end = start | ~mask;
@@ -241,9 +241,9 @@ void __init mips_pcibios_init(void)
return;
}
- /* Change start address to avoid conflicts with ACPI and SMB devices */
- if (controller->io_resource->start < 0x00002000UL)
- controller->io_resource->start = 0x00002000UL;
+ /* PIIX4 ACPI starts at 0x1000 */
+ if (controller->io_resource->start < 0x00001000UL)
+ controller->io_resource->start = 0x00001000UL;
iomem_resource.end &= 0xfffffffffULL; /* 64 GB */
ioport_resource.end = controller->io_resource->end;
diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c
index b128cb973eb..7f6ce6d734c 100644
--- a/arch/mips/pci/pci-rc32434.c
+++ b/arch/mips/pci/pci-rc32434.c
@@ -53,7 +53,6 @@ static struct resource rc32434_res_pci_mem1 = {
.start = 0x50000000,
.end = 0x5FFFFFFF,
.flags = IORESOURCE_MEM,
- .parent = &rc32434_res_pci_mem1,
.sibling = NULL,
.child = &rc32434_res_pci_mem2
};
diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c
index 95c9d41382e..72919aeef42 100644
--- a/arch/mips/pci/pci-rt3883.c
+++ b/arch/mips/pci/pci-rt3883.c
@@ -436,9 +436,6 @@ static int rt3883_pci_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
rpc->base = devm_ioremap_resource(dev, res);
if (IS_ERR(rpc->base))
return PTR_ERR(rpc->base);
@@ -583,29 +580,7 @@ err_put_intc_node:
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
- struct of_irq dev_irq;
- int err;
- int irq;
-
- err = of_irq_map_pci(dev, &dev_irq);
- if (err) {
- pr_err("pci %s: unable to get irq map, err=%d\n",
- pci_name((struct pci_dev *) dev), err);
- return 0;
- }
-
- irq = irq_create_of_mapping(dev_irq.controller,
- dev_irq.specifier,
- dev_irq.size);
-
- if (irq == 0)
- pr_crit("pci %s: no irq found for pin %u\n",
- pci_name((struct pci_dev *) dev), pin);
- else
- pr_info("pci %s: using irq %d for pin %u\n",
- pci_name((struct pci_dev *) dev), irq, pin);
-
- return irq;
+ return of_irq_parse_and_map_pci(dev, slot, pin);
}
int pcibios_plat_dev_init(struct pci_dev *dev)
diff --git a/arch/mips/pci/pci-virtio-guest.c b/arch/mips/pci/pci-virtio-guest.c
new file mode 100644
index 00000000000..40a078bc461
--- /dev/null
+++ b/arch/mips/pci/pci-virtio-guest.c
@@ -0,0 +1,131 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Cavium, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#include <uapi/asm/bitfield.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#define PCI_CONFIG_ADDRESS 0xcf8
+#define PCI_CONFIG_DATA 0xcfc
+
+union pci_config_address {
+ struct {
+ __BITFIELD_FIELD(unsigned enable_bit : 1, /* 31 */
+ __BITFIELD_FIELD(unsigned reserved : 7, /* 30 .. 24 */
+ __BITFIELD_FIELD(unsigned bus_number : 8, /* 23 .. 16 */
+ __BITFIELD_FIELD(unsigned devfn_number : 8, /* 15 .. 8 */
+ __BITFIELD_FIELD(unsigned register_number : 8, /* 7 .. 0 */
+ )))));
+ };
+ u32 w;
+};
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return ((pin + slot) % 4)+ MIPS_IRQ_PCIA;
+}
+
+static void pci_virtio_guest_write_config_addr(struct pci_bus *bus,
+ unsigned int devfn, int reg)
+{
+ union pci_config_address pca = { .w = 0 };
+
+ pca.register_number = reg;
+ pca.devfn_number = devfn;
+ pca.bus_number = bus->number;
+ pca.enable_bit = 1;
+
+ outl(pca.w, PCI_CONFIG_ADDRESS);
+}
+
+static int pci_virtio_guest_write_config(struct pci_bus *bus,
+ unsigned int devfn, int reg, int size, u32 val)
+{
+ pci_virtio_guest_write_config_addr(bus, devfn, reg);
+
+ switch (size) {
+ case 1:
+ outb(val, PCI_CONFIG_DATA + (reg & 3));
+ break;
+ case 2:
+ outw(val, PCI_CONFIG_DATA + (reg & 2));
+ break;
+ case 4:
+ outl(val, PCI_CONFIG_DATA);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_virtio_guest_read_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 *val)
+{
+ pci_virtio_guest_write_config_addr(bus, devfn, reg);
+
+ switch (size) {
+ case 1:
+ *val = inb(PCI_CONFIG_DATA + (reg & 3));
+ break;
+ case 2:
+ *val = inw(PCI_CONFIG_DATA + (reg & 2));
+ break;
+ case 4:
+ *val = inl(PCI_CONFIG_DATA);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_virtio_guest_ops = {
+ .read = pci_virtio_guest_read_config,
+ .write = pci_virtio_guest_write_config,
+};
+
+static struct resource pci_virtio_guest_mem_resource = {
+ .name = "Virtio MEM",
+ .flags = IORESOURCE_MEM,
+ .start = 0x10000000,
+ .end = 0x1dffffff
+};
+
+static struct resource pci_virtio_guest_io_resource = {
+ .name = "Virtio IO",
+ .flags = IORESOURCE_IO,
+ .start = 0,
+ .end = 0xffff
+};
+
+static struct pci_controller pci_virtio_guest_controller = {
+ .pci_ops = &pci_virtio_guest_ops,
+ .mem_resource = &pci_virtio_guest_mem_resource,
+ .io_resource = &pci_virtio_guest_io_resource,
+};
+
+static int __init pci_virtio_guest_setup(void)
+{
+ pr_err("pci_virtio_guest_setup\n");
+
+ /* Virtio comes pre-assigned */
+ pci_set_flags(PCI_PROBE_ONLY);
+
+ pci_virtio_guest_controller.io_map_base = mips_io_port_base;
+ register_pci_controller(&pci_virtio_guest_controller);
+ return 0;
+}
+arch_initcall(pci_virtio_guest_setup);
diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c
index 653d2db9e0c..7babf01600c 100644
--- a/arch/mips/pci/pci-xlp.c
+++ b/arch/mips/pci/pci-xlp.c
@@ -47,10 +47,11 @@
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
+#include <asm/netlogic/mips-extns.h>
#include <asm/netlogic/xlp-hal/iomap.h>
-#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/xlp.h>
+#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/pcibus.h>
#include <asm/netlogic/xlp-hal/bridge.h>
@@ -66,9 +67,22 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,
u32 *cfgaddr;
where &= ~3;
- if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954)
+ if (cpu_is_xlp9xx()) {
+ /* be very careful on SoC buses */
+ if (bus->number == 0) {
+ /* Scan only existing nodes - uboot bug? */
+ if (PCI_SLOT(devfn) != 0 ||
+ !nlm_node_present(PCI_FUNC(devfn)))
+ return 0xffffffff;
+ } else if (bus->parent->number == 0) { /* SoC bus */
+ if (PCI_SLOT(devfn) == 0) /* b.0.0 hangs */
+ return 0xffffffff;
+ if (devfn == 44) /* b.5.4 hangs */
+ return 0xffffffff;
+ }
+ } else if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) {
return 0xffffffff;
-
+ }
cfgaddr = (u32 *)(pci_config_base +
pci_cfg_addr(bus->number, devfn, where));
data = *cfgaddr;
@@ -162,27 +176,39 @@ struct pci_controller nlm_pci_controller = {
.io_offset = 0x00000000UL,
};
-static struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)
+struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)
{
struct pci_bus *bus, *p;
- /* Find the bridge on bus 0 */
bus = dev->bus;
- for (p = bus->parent; p && p->number != 0; p = p->parent)
- bus = p;
- return p ? bus->self : NULL;
+ if (cpu_is_xlp9xx()) {
+ /* find bus with grand parent number == 0 */
+ for (p = bus->parent; p && p->parent && p->parent->number != 0;
+ p = p->parent)
+ bus = p;
+ return (p && p->parent) ? bus->self : NULL;
+ } else {
+ /* Find the bridge on bus 0 */
+ for (p = bus->parent; p && p->number != 0; p = p->parent)
+ bus = p;
+
+ return p ? bus->self : NULL;
+ }
}
-static inline int nlm_pci_link_to_irq(int link)
+int xlp_socdev_to_node(const struct pci_dev *lnkdev)
{
- return PIC_PCIE_LINK_0_IRQ + link;
+ if (cpu_is_xlp9xx())
+ return PCI_FUNC(lnkdev->bus->self->devfn);
+ else
+ return PCI_SLOT(lnkdev->devfn) / 8;
}
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_dev *lnkdev;
- int lnkslot, lnkfunc;
+ int lnkfunc, node;
/*
* For XLP PCIe, there is an IRQ per Link, find out which
@@ -191,9 +217,11 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
lnkdev = xlp_get_pcie_link(dev);
if (lnkdev == NULL)
return 0;
+
lnkfunc = PCI_FUNC(lnkdev->devfn);
- lnkslot = PCI_SLOT(lnkdev->devfn);
- return nlm_irq_to_xirq(lnkslot / 8, nlm_pci_link_to_irq(lnkfunc));
+ node = xlp_socdev_to_node(lnkdev);
+
+ return nlm_irq_to_xirq(node, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc));
}
/* Do platform specific device initialization at pci_enable_device() time */
@@ -220,17 +248,38 @@ static void xlp_config_pci_bswap(int node, int link)
* Enable byte swap in hardware. Program each link's PCIe SWAP regions
* from the link's address ranges.
*/
- reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link);
- nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg);
-
- reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_LIMIT0 + link);
- nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff);
-
- reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link);
- nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg);
-
- reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link);
- nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff);
+ if (cpu_is_xlp9xx()) {
+ reg = nlm_read_bridge_reg(nbubase,
+ BRIDGE_9XX_PCIEMEM_BASE0 + link);
+ nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_MEM_BASE, reg);
+
+ reg = nlm_read_bridge_reg(nbubase,
+ BRIDGE_9XX_PCIEMEM_LIMIT0 + link);
+ nlm_write_pci_reg(lnkbase,
+ PCIE_9XX_BYTE_SWAP_MEM_LIM, reg | 0xfff);
+
+ reg = nlm_read_bridge_reg(nbubase,
+ BRIDGE_9XX_PCIEIO_BASE0 + link);
+ nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_IO_BASE, reg);
+
+ reg = nlm_read_bridge_reg(nbubase,
+ BRIDGE_9XX_PCIEIO_LIMIT0 + link);
+ nlm_write_pci_reg(lnkbase,
+ PCIE_9XX_BYTE_SWAP_IO_LIM, reg | 0xfff);
+ } else {
+ reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link);
+ nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg);
+
+ reg = nlm_read_bridge_reg(nbubase,
+ BRIDGE_PCIEMEM_LIMIT0 + link);
+ nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff);
+
+ reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link);
+ nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg);
+
+ reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link);
+ nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff);
+ }
}
#else
/* Swap configuration not needed in little-endian mode */
@@ -239,7 +288,6 @@ static inline void xlp_config_pci_bswap(int node, int link) {}
static int __init pcibios_init(void)
{
- struct nlm_soc_info *nodep;
uint64_t pciebase;
int link, n;
u32 reg;
@@ -253,20 +301,20 @@ static int __init pcibios_init(void)
ioport_resource.end = ~0;
for (n = 0; n < NLM_NR_NODES; n++) {
- nodep = nlm_get_node(n);
- if (!nodep->coremask)
- continue; /* node does not exist */
+ if (!nlm_node_present(n))
+ continue;
- for (link = 0; link < 4; link++) {
+ for (link = 0; link < PCIE_NLINKS; link++) {
pciebase = nlm_get_pcie_base(n, link);
if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff)
continue;
xlp_config_pci_bswap(n, link);
+ xlp_init_node_msi_irqs(n, link);
/* put in intpin and irq - u-boot does not */
reg = nlm_read_pci_reg(pciebase, 0xf);
- reg &= ~0x1fu;
- reg |= (1 << 8) | nlm_pci_link_to_irq(link);
+ reg &= ~0x1ffu;
+ reg |= (1 << 8) | PIC_PCIE_LINK_LEGACY_IRQ(link);
nlm_write_pci_reg(pciebase, 0xf, reg);
pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link);
}
diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c
index 4427abbd48b..0dde80332d3 100644
--- a/arch/mips/pci/pci-xlr.c
+++ b/arch/mips/pci/pci-xlr.c
@@ -214,14 +214,8 @@ static int get_irq_vector(const struct pci_dev *dev)
}
#ifdef CONFIG_PCI_MSI
-void destroy_irq(unsigned int irq)
-{
- /* nothing to do yet */
-}
-
void arch_teardown_msi_irq(unsigned int irq)
{
- destroy_irq(irq);
}
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
@@ -263,10 +257,8 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
MSI_DATA_DELIVERY_FIXED;
ret = irq_set_msi_desc(irq, desc);
- if (ret < 0) {
- destroy_irq(irq);
+ if (ret < 0)
return ret;
- }
write_msi_msg(irq, &msg);
return 0;
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 33e7aa52d9c..1bf60b12737 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -120,51 +120,37 @@ static void pcibios_scanbus(struct pci_controller *hose)
#ifdef CONFIG_OF
void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node)
{
- const __be32 *ranges;
- int rlen;
- int pna = of_n_addr_cells(node);
- int np = pna + 5;
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
pr_info("PCI host bridge %s ranges:\n", node->full_name);
- ranges = of_get_property(node, "ranges", &rlen);
- if (ranges == NULL)
- return;
hose->of_node = node;
- while ((rlen -= np * 4) >= 0) {
- u32 pci_space;
+ if (of_pci_range_parser_init(&parser, node))
+ return;
+
+ for_each_of_pci_range(&parser, &range) {
struct resource *res = NULL;
- u64 addr, size;
-
- pci_space = be32_to_cpup(&ranges[0]);
- addr = of_translate_address(node, ranges + 3);
- size = of_read_number(ranges + pna + 3, 2);
- ranges += np;
- switch ((pci_space >> 24) & 0x3) {
- case 1: /* PCI IO space */
+
+ switch (range.flags & IORESOURCE_TYPE_BITS) {
+ case IORESOURCE_IO:
pr_info(" IO 0x%016llx..0x%016llx\n",
- addr, addr + size - 1);
+ range.cpu_addr,
+ range.cpu_addr + range.size - 1);
hose->io_map_base =
- (unsigned long)ioremap(addr, size);
+ (unsigned long)ioremap(range.cpu_addr,
+ range.size);
res = hose->io_resource;
- res->flags = IORESOURCE_IO;
break;
- case 2: /* PCI Memory space */
- case 3: /* PCI 64 bits Memory space */
+ case IORESOURCE_MEM:
pr_info(" MEM 0x%016llx..0x%016llx\n",
- addr, addr + size - 1);
+ range.cpu_addr,
+ range.cpu_addr + range.size - 1);
res = hose->mem_resource;
- res->flags = IORESOURCE_MEM;
break;
}
- if (res != NULL) {
- res->start = addr;
- res->name = node->full_name;
- res->end = res->start + size - 1;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
- }
+ if (res != NULL)
+ of_pci_range_to_resource(&range, node, res);
}
}
diff --git a/arch/mips/pmcs-msp71xx/Kconfig b/arch/mips/pmcs-msp71xx/Kconfig
index 3482b8c8640..6073ca456d1 100644
--- a/arch/mips/pmcs-msp71xx/Kconfig
+++ b/arch/mips/pmcs-msp71xx/Kconfig
@@ -6,6 +6,7 @@ config PMC_MSP4200_EVAL
bool "PMC-Sierra MSP4200 Eval Board"
select IRQ_MSP_SLP
select HW_HAS_PCI
+ select MIPS_L1_CACHE_SHIFT_4
config PMC_MSP4200_GW
bool "PMC-Sierra MSP4200 VoIP Gateway"
diff --git a/arch/mips/pmcs-msp71xx/Makefile b/arch/mips/pmcs-msp71xx/Makefile
index 9201c8b3858..d4f7220f248 100644
--- a/arch/mips/pmcs-msp71xx/Makefile
+++ b/arch/mips/pmcs-msp71xx/Makefile
@@ -10,4 +10,3 @@ obj-$(CONFIG_PCI) += msp_pci.o
obj-$(CONFIG_MSP_HAS_MAC) += msp_eth.o
obj-$(CONFIG_MSP_HAS_USB) += msp_usb.o
obj-$(CONFIG_MIPS_MT_SMP) += msp_smp.o
-obj-$(CONFIG_MIPS_MT_SMTC) += msp_smtc.o
diff --git a/arch/mips/pmcs-msp71xx/msp_eth.c b/arch/mips/pmcs-msp71xx/msp_eth.c
index c584df393de..15679b427f4 100644
--- a/arch/mips/pmcs-msp71xx/msp_eth.c
+++ b/arch/mips/pmcs-msp71xx/msp_eth.c
@@ -38,73 +38,6 @@
#define MSP_ETHERNET_GPIO1 15
#define MSP_ETHERNET_GPIO2 16
-#ifdef CONFIG_MSP_HAS_TSMAC
-#define MSP_TSMAC_SIZE 0x10020
-#define MSP_TSMAC_ID "pmc_tsmac"
-
-static struct resource msp_tsmac0_resources[] = {
- [0] = {
- .start = MSP_MAC0_BASE,
- .end = MSP_MAC0_BASE + MSP_TSMAC_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = MSP_INT_MAC0,
- .end = MSP_INT_MAC0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource msp_tsmac1_resources[] = {
- [0] = {
- .start = MSP_MAC1_BASE,
- .end = MSP_MAC1_BASE + MSP_TSMAC_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = MSP_INT_MAC1,
- .end = MSP_INT_MAC1,
- .flags = IORESOURCE_IRQ,
- },
-};
-static struct resource msp_tsmac2_resources[] = {
- [0] = {
- .start = MSP_MAC2_BASE,
- .end = MSP_MAC2_BASE + MSP_TSMAC_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = MSP_INT_SAR,
- .end = MSP_INT_SAR,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-
-static struct platform_device tsmac_device[] = {
- [0] = {
- .name = MSP_TSMAC_ID,
- .id = 0,
- .num_resources = ARRAY_SIZE(msp_tsmac0_resources),
- .resource = msp_tsmac0_resources,
- },
- [1] = {
- .name = MSP_TSMAC_ID,
- .id = 1,
- .num_resources = ARRAY_SIZE(msp_tsmac1_resources),
- .resource = msp_tsmac1_resources,
- },
- [2] = {
- .name = MSP_TSMAC_ID,
- .id = 2,
- .num_resources = ARRAY_SIZE(msp_tsmac2_resources),
- .resource = msp_tsmac2_resources,
- },
-};
-#define msp_eth_devs tsmac_device
-
-#else
-/* If it is not TSMAC assume MSP_ETH (100Mbps) */
#define MSP_ETH_ID "pmc_mspeth"
#define MSP_ETH_SIZE 0xE0
static struct resource msp_eth0_resources[] = {
@@ -152,7 +85,6 @@ static struct platform_device mspeth_device[] = {
};
#define msp_eth_devs mspeth_device
-#endif
int __init msp_eth_setup(void)
{
int i, ret = 0;
@@ -161,14 +93,6 @@ int __init msp_eth_setup(void)
msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO0);
msp_gpio_pin_hi(MSP_ETHERNET_GPIO0);
-#ifdef CONFIG_MSP_HAS_TSMAC
- /* 3 phys on boards with TSMAC */
- msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO1);
- msp_gpio_pin_hi(MSP_ETHERNET_GPIO1);
-
- msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO2);
- msp_gpio_pin_hi(MSP_ETHERNET_GPIO2);
-#endif
for (i = 0; i < ARRAY_SIZE(msp_eth_devs); i++) {
ret = platform_device_register(&msp_eth_devs[i]);
printk(KERN_INFO "device: %d, return value = %d\n", i, ret);
diff --git a/arch/mips/pmcs-msp71xx/msp_irq.c b/arch/mips/pmcs-msp71xx/msp_irq.c
index 9da5619c00a..941744aabb5 100644
--- a/arch/mips/pmcs-msp71xx/msp_irq.c
+++ b/arch/mips/pmcs-msp71xx/msp_irq.c
@@ -32,7 +32,7 @@ extern void msp_vsmp_int_init(void);
/* vectored interrupt implementation */
-/* SW0/1 interrupts are used for SMP/SMTC */
+/* SW0/1 interrupts are used for SMP */
static inline void mac0_int_dispatch(void) { do_IRQ(MSP_INT_MAC0); }
static inline void mac1_int_dispatch(void) { do_IRQ(MSP_INT_MAC1); }
static inline void mac2_int_dispatch(void) { do_IRQ(MSP_INT_SAR); }
@@ -138,14 +138,6 @@ void __init arch_init_irq(void)
set_vi_handler(MSP_INT_SEC, sec_int_dispatch);
#ifdef CONFIG_MIPS_MT_SMP
msp_vsmp_int_init();
-#elif defined CONFIG_MIPS_MT_SMTC
- /*Set hwmask for all platform devices */
- irq_hwmask[MSP_INT_MAC0] = C_IRQ0;
- irq_hwmask[MSP_INT_MAC1] = C_IRQ1;
- irq_hwmask[MSP_INT_USB] = C_IRQ2;
- irq_hwmask[MSP_INT_SAR] = C_IRQ3;
- irq_hwmask[MSP_INT_SEC] = C_IRQ5;
-
#endif /* CONFIG_MIPS_MT_SMP */
#endif /* CONFIG_MIPS_MT */
/* setup the cascaded interrupts */
@@ -153,8 +145,10 @@ void __init arch_init_irq(void)
setup_irq(MSP_INT_PER, &per_cascade_msp);
#else
- /* setup the 2nd-level SLP register based interrupt controller */
- /* VSMP /SMTC support support is not enabled for SLP */
+ /*
+ * Setup the 2nd-level SLP register based interrupt controller.
+ * VSMP support support is not enabled for SLP.
+ */
msp_slp_irq_init();
/* setup the cascaded SLP/PER interrupts */
diff --git a/arch/mips/pmcs-msp71xx/msp_irq_cic.c b/arch/mips/pmcs-msp71xx/msp_irq_cic.c
index e49b499f66d..b8df2f7b332 100644
--- a/arch/mips/pmcs-msp71xx/msp_irq_cic.c
+++ b/arch/mips/pmcs-msp71xx/msp_irq_cic.c
@@ -120,10 +120,9 @@ static void msp_cic_irq_ack(struct irq_data *d)
* hurt for the others
*/
*CIC_STS_REG = (1 << (d->irq - MSP_CIC_INTBASE));
- smtc_im_ack_irq(d->irq);
}
-/*Note: Limiting to VSMP . Not tested in SMTC */
+/* Note: Limiting to VSMP. */
#ifdef CONFIG_MIPS_MT_SMP
static int msp_cic_irq_set_affinity(struct irq_data *d,
@@ -183,10 +182,6 @@ void __init msp_cic_irq_init(void)
for (i = MSP_CIC_INTBASE ; i < MSP_CIC_INTBASE + 32 ; i++) {
irq_set_chip_and_handler(i, &msp_cic_irq_controller,
handle_level_irq);
-#ifdef CONFIG_MIPS_MT_SMTC
- /* Mask of CIC interrupt */
- irq_hwmask[i] = C_IRQ4;
-#endif
}
/* Initialize the PER interrupt sub-system */
diff --git a/arch/mips/pmcs-msp71xx/msp_irq_per.c b/arch/mips/pmcs-msp71xx/msp_irq_per.c
index d1fd530479d..a111836bcec 100644
--- a/arch/mips/pmcs-msp71xx/msp_irq_per.c
+++ b/arch/mips/pmcs-msp71xx/msp_irq_per.c
@@ -113,9 +113,6 @@ void __init msp_per_irq_init(void)
/* initialize all the IRQ descriptors */
for (i = MSP_PER_INTBASE; i < MSP_PER_INTBASE + 32; i++) {
irq_set_chip(i, &msp_per_irq_controller);
-#ifdef CONFIG_MIPS_MT_SMTC
- irq_hwmask[i] = C_IRQ4;
-#endif
}
}
diff --git a/arch/mips/pmcs-msp71xx/msp_setup.c b/arch/mips/pmcs-msp71xx/msp_setup.c
index 396b2967ad8..4f925e06c41 100644
--- a/arch/mips/pmcs-msp71xx/msp_setup.c
+++ b/arch/mips/pmcs-msp71xx/msp_setup.c
@@ -27,7 +27,6 @@
#endif
extern void msp_serial_setup(void);
-extern void pmctwiled_setup(void);
#if defined(CONFIG_PMC_MSP7120_EVAL) || \
defined(CONFIG_PMC_MSP7120_GW) || \
@@ -49,7 +48,7 @@ void msp7120_reset(void)
/* Cache the reset code of this function */
__asm__ __volatile__ (
" .set push \n"
- " .set mips3 \n"
+ " .set arch=r4000 \n"
" la %0,startpoint \n"
" la %1,endpoint \n"
" .set pop \n"
@@ -148,8 +147,6 @@ void __init plat_mem_setup(void)
pm_power_off = msp_power_off;
}
-extern struct plat_smp_ops msp_smtc_smp_ops;
-
void __init prom_init(void)
{
unsigned long family;
@@ -230,17 +227,5 @@ void __init prom_init(void)
*/
msp_serial_setup();
- if (register_vsmp_smp_ops()) {
-#ifdef CONFIG_MIPS_MT_SMTC
- register_smp_ops(&msp_smtc_smp_ops);
-#endif
- }
-
-#ifdef CONFIG_PMCTWILED
- /*
- * Setup LED states before the subsys_initcall loads other
- * dependent drivers/modules.
- */
- pmctwiled_setup();
-#endif
+ register_vsmp_smp_ops();
}
diff --git a/arch/mips/pmcs-msp71xx/msp_smtc.c b/arch/mips/pmcs-msp71xx/msp_smtc.c
deleted file mode 100644
index 6b5607fce27..00000000000
--- a/arch/mips/pmcs-msp71xx/msp_smtc.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * MSP71xx Platform-specific hooks for SMP operation
- */
-#include <linux/irq.h>
-#include <linux/init.h>
-
-#include <asm/mipsmtregs.h>
-#include <asm/mipsregs.h>
-#include <asm/smtc.h>
-#include <asm/smtc_ipi.h>
-
-/* VPE/SMP Prototype implements platform interfaces directly */
-
-/*
- * Cause the specified action to be performed on a targeted "CPU"
- */
-
-static void msp_smtc_send_ipi_single(int cpu, unsigned int action)
-{
- /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
- smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
-}
-
-static void msp_smtc_send_ipi_mask(const struct cpumask *mask,
- unsigned int action)
-{
- unsigned int i;
-
- for_each_cpu(i, mask)
- msp_smtc_send_ipi_single(i, action);
-}
-
-/*
- * Post-config but pre-boot cleanup entry point
- */
-static void msp_smtc_init_secondary(void)
-{
- int myvpe;
-
- /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
- myvpe = read_c0_tcbind() & TCBIND_CURVPE;
- if (myvpe > 0)
- change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 |
- STATUSF_IP6 | STATUSF_IP7);
- smtc_init_secondary();
-}
-
-/*
- * Platform "CPU" startup hook
- */
-static void msp_smtc_boot_secondary(int cpu, struct task_struct *idle)
-{
- smtc_boot_secondary(cpu, idle);
-}
-
-/*
- * SMP initialization finalization entry point
- */
-static void msp_smtc_smp_finish(void)
-{
- smtc_smp_finish();
-}
-
-/*
- * Hook for after all CPUs are online
- */
-
-static void msp_smtc_cpus_done(void)
-{
-}
-
-/*
- * Platform SMP pre-initialization
- *
- * As noted above, we can assume a single CPU for now
- * but it may be multithreaded.
- */
-
-static void __init msp_smtc_smp_setup(void)
-{
- /*
- * we won't get the definitive value until
- * we've run smtc_prepare_cpus later, but
- */
-
- if (read_c0_config3() & (1 << 2))
- smp_num_siblings = smtc_build_cpu_map(0);
-}
-
-static void __init msp_smtc_prepare_cpus(unsigned int max_cpus)
-{
- smtc_prepare_cpus(max_cpus);
-}
-
-struct plat_smp_ops msp_smtc_smp_ops = {
- .send_ipi_single = msp_smtc_send_ipi_single,
- .send_ipi_mask = msp_smtc_send_ipi_mask,
- .init_secondary = msp_smtc_init_secondary,
- .smp_finish = msp_smtc_smp_finish,
- .cpus_done = msp_smtc_cpus_done,
- .boot_secondary = msp_smtc_boot_secondary,
- .smp_setup = msp_smtc_smp_setup,
- .prepare_cpus = msp_smtc_prepare_cpus,
-};
diff --git a/arch/mips/pmcs-msp71xx/msp_usb.c b/arch/mips/pmcs-msp71xx/msp_usb.c
index 4dab915696e..c87c5f810cd 100644
--- a/arch/mips/pmcs-msp71xx/msp_usb.c
+++ b/arch/mips/pmcs-msp71xx/msp_usb.c
@@ -75,47 +75,6 @@ static struct mspusb_device msp_usbhost0_device = {
.resource = msp_usbhost0_resources,
},
};
-
-/* MSP7140/MSP82XX has two USB2 hosts. */
-#ifdef CONFIG_MSP_HAS_DUAL_USB
-static u64 msp_usbhost1_dma_mask = 0xffffffffUL;
-
-static struct resource msp_usbhost1_resources[] = {
- [0] = { /* EHCI-HS operational and capabilities registers */
- .start = MSP_USB1_HS_START,
- .end = MSP_USB1_HS_END,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = MSP_INT_USB,
- .end = MSP_INT_USB,
- .flags = IORESOURCE_IRQ,
- },
- [2] = { /* MSBus-to-AMBA bridge register space */
- .start = MSP_USB1_MAB_START,
- .end = MSP_USB1_MAB_END,
- .flags = IORESOURCE_MEM,
- },
- [3] = { /* Identification and general hardware parameters */
- .start = MSP_USB1_ID_START,
- .end = MSP_USB1_ID_END,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct mspusb_device msp_usbhost1_device = {
- .dev = {
- .name = "pmcmsp-ehci",
- .id = 1,
- .dev = {
- .dma_mask = &msp_usbhost1_dma_mask,
- .coherent_dma_mask = 0xffffffffUL,
- },
- .num_resources = ARRAY_SIZE(msp_usbhost1_resources),
- .resource = msp_usbhost1_resources,
- },
-};
-#endif /* CONFIG_MSP_HAS_DUAL_USB */
#endif /* CONFIG_USB_EHCI_HCD */
#if defined(CONFIG_USB_GADGET)
@@ -157,46 +116,6 @@ static struct mspusb_device msp_usbdev0_device = {
.resource = msp_usbdev0_resources,
},
};
-
-#ifdef CONFIG_MSP_HAS_DUAL_USB
-static struct resource msp_usbdev1_resources[] = {
- [0] = { /* EHCI-HS operational and capabilities registers */
- .start = MSP_USB1_HS_START,
- .end = MSP_USB1_HS_END,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = MSP_INT_USB,
- .end = MSP_INT_USB,
- .flags = IORESOURCE_IRQ,
- },
- [2] = { /* MSBus-to-AMBA bridge register space */
- .start = MSP_USB1_MAB_START,
- .end = MSP_USB1_MAB_END,
- .flags = IORESOURCE_MEM,
- },
- [3] = { /* Identification and general hardware parameters */
- .start = MSP_USB1_ID_START,
- .end = MSP_USB1_ID_END,
- .flags = IORESOURCE_MEM,
- },
-};
-
-/* This may need to be converted to a mspusb_device, too. */
-static struct mspusb_device msp_usbdev1_device = {
- .dev = {
- .name = "msp71xx_udc",
- .id = 0,
- .dev = {
- .dma_mask = &msp_usbdev_dma_mask,
- .coherent_dma_mask = 0xffffffffUL,
- },
- .num_resources = ARRAY_SIZE(msp_usbdev1_resources),
- .resource = msp_usbdev1_resources,
- },
-};
-
-#endif /* CONFIG_MSP_HAS_DUAL_USB */
#endif /* CONFIG_USB_GADGET */
static int __init msp_usb_setup(void)
@@ -231,10 +150,6 @@ static int __init msp_usb_setup(void)
#if defined(CONFIG_USB_EHCI_HCD)
msp_devs[0] = &msp_usbhost0_device.dev;
ppfinit("platform add USB HOST done %s.\n", msp_devs[0]->name);
-#ifdef CONFIG_MSP_HAS_DUAL_USB
- msp_devs[1] = &msp_usbhost1_device.dev;
- ppfinit("platform add USB HOST done %s.\n", msp_devs[1]->name);
-#endif
#else
ppfinit("%s: echi_hcd not supported\n", __FILE__);
#endif /* CONFIG_USB_EHCI_HCD */
@@ -244,11 +159,6 @@ static int __init msp_usb_setup(void)
msp_devs[0] = &msp_usbdev0_device.dev;
ppfinit("platform add USB DEVICE done %s.\n"
, msp_devs[0]->name);
-#ifdef CONFIG_MSP_HAS_DUAL_USB
- msp_devs[1] = &msp_usbdev1_device.dev;
- ppfinit("platform add USB DEVICE done %s.\n"
- , msp_devs[1]->name);
-#endif
#else
ppfinit("%s: usb_gadget not supported\n", __FILE__);
#endif /* CONFIG_USB_GADGET */
diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c
index 2b7e837dc2e..b4b774bc317 100644
--- a/arch/mips/pnx833x/common/platform.c
+++ b/arch/mips/pnx833x/common/platform.c
@@ -33,11 +33,6 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
-#ifdef CONFIG_I2C_PNX0105
-/* Until i2c driver available in kernel.*/
-#include <linux/i2c-pnx0105.h>
-#endif
-
#include <irq.h>
#include <irq-mapping.h>
#include <pnx833x.h>
@@ -134,70 +129,6 @@ static struct platform_device pnx833x_usb_ehci_device = {
.resource = pnx833x_usb_ehci_resources,
};
-#ifdef CONFIG_I2C_PNX0105
-static struct resource pnx833x_i2c0_resources[] = {
- {
- .start = PNX833X_I2C0_PORTS_START,
- .end = PNX833X_I2C0_PORTS_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = PNX833X_PIC_I2C0_INT,
- .end = PNX833X_PIC_I2C0_INT,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource pnx833x_i2c1_resources[] = {
- {
- .start = PNX833X_I2C1_PORTS_START,
- .end = PNX833X_I2C1_PORTS_END,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = PNX833X_PIC_I2C1_INT,
- .end = PNX833X_PIC_I2C1_INT,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = {
- {
- .base = PNX833X_I2C0_PORTS_START,
- .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */
- .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Preferred HDCP) */
- .bus_addr = 0, /* no slave support */
- },
- {
- .base = PNX833X_I2C1_PORTS_START,
- .irq = -1, /* on high freq, polling is faster */
- /*.irq = PNX833X_PIC_I2C1_INT,*/
- .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz seems a safe default for now */
- .bus_addr = 0, /* no slave support */
- },
-};
-
-static struct platform_device pnx833x_i2c0_device = {
- .name = "i2c-pnx0105",
- .id = 0,
- .dev = {
- .platform_data = &pnx833x_i2c_dev[0],
- },
- .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources),
- .resource = pnx833x_i2c0_resources,
-};
-
-static struct platform_device pnx833x_i2c1_device = {
- .name = "i2c-pnx0105",
- .id = 1,
- .dev = {
- .platform_data = &pnx833x_i2c_dev[1],
- },
- .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources),
- .resource = pnx833x_i2c1_resources,
-};
-#endif
-
static u64 ethernet_dmamask = DMA_BIT_MASK(32);
static struct resource pnx833x_ethernet_resources[] = {
@@ -294,10 +225,6 @@ static struct platform_device pnx833x_flash_nand = {
static struct platform_device *pnx833x_platform_devices[] __initdata = {
&pnx833x_uart_device,
&pnx833x_usb_ehci_device,
-#ifdef CONFIG_I2C_PNX0105
- &pnx833x_i2c0_device,
- &pnx833x_i2c1_device,
-#endif
&pnx833x_ethernet_device,
&pnx833x_sata_device,
&pnx833x_flash_nand,
diff --git a/arch/mips/power/hibernate.S b/arch/mips/power/hibernate.S
index 7e0277a1048..32a7c828f07 100644
--- a/arch/mips/power/hibernate.S
+++ b/arch/mips/power/hibernate.S
@@ -43,6 +43,7 @@ LEAF(swsusp_arch_resume)
bne t1, t3, 1b
PTR_L t0, PBE_NEXT(t0)
bnez t0, 0b
+ jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
PTR_LA t0, saved_regs
PTR_L ra, PT_R31(t0)
PTR_L sp, PT_R29(t0)
diff --git a/arch/mips/powertv/Kconfig b/arch/mips/powertv/Kconfig
deleted file mode 100644
index dd91fbacbcb..00000000000
--- a/arch/mips/powertv/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-config BOOTLOADER_FAMILY
- string "POWERTV Bootloader Family string"
- default "85"
- depends on POWERTV
- help
- This value should be specified when the bootloader driver is disabled
- and must be exactly two characters long. Families supported are:
- R1 - RNG-100 R2 - RNG-200
- A1 - Class A B1 - Class B
- E1 - Class E F1 - Class F
- 44 - 45xx 46 - 46xx
- 85 - 85xx 86 - 86xx
diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile
deleted file mode 100644
index 39ca9f8d63a..00000000000
--- a/arch/mips/powertv/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Carsten Langgaard, carstenl@mips.com
-# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
-#
-# Carsten Langgaard, carstenl@mips.com
-# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
-# Portions copyright (C) 2009 Cisco Systems, Inc.
-#
-# This program is free software; you can distribute it and/or modify it
-# under the terms of the GNU General Public License (Version 2) as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-# Makefile for the Cisco PowerTV-specific kernel interface routines
-# under Linux.
-#
-
-obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \
- asic/ pci/
-
-obj-$(CONFIG_USB) += powertv-usb.o
diff --git a/arch/mips/powertv/Platform b/arch/mips/powertv/Platform
deleted file mode 100644
index 4eb5af1d8ee..00000000000
--- a/arch/mips/powertv/Platform
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Cisco PowerTV Platform
-#
-platform-$(CONFIG_POWERTV) += powertv/
-cflags-$(CONFIG_POWERTV) += \
- -I$(srctree)/arch/mips/include/asm/mach-powertv
-load-$(CONFIG_POWERTV) += 0xffffffff90800000
diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile
deleted file mode 100644
index 35dcc53eb25..00000000000
--- a/arch/mips/powertv/asic/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright (C) 2009 Scientific-Atlanta, 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.
-#
-# 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
-#
-
-obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \
- asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \
- prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
diff --git a/arch/mips/powertv/asic/asic-calliope.c b/arch/mips/powertv/asic/asic-calliope.c
deleted file mode 100644
index 2f539b43f56..00000000000
--- a/arch/mips/powertv/asic/asic-calliope.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Calliope ASIC.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * Description: Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define CALLIOPE_ADDR(x) (CALLIOPE_IO_BASE + (x))
-
-const struct register_map calliope_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = CALLIOPE_ADDR(0x800000)},
- .eic_cfg_bits = {.phys = CALLIOPE_ADDR(0x800038)},
- .eic_ready_status = {.phys = CALLIOPE_ADDR(0x80004c)},
-
- .chipver3 = {.phys = CALLIOPE_ADDR(0xA00800)},
- .chipver2 = {.phys = CALLIOPE_ADDR(0xA00804)},
- .chipver1 = {.phys = CALLIOPE_ADDR(0xA00808)},
- .chipver0 = {.phys = CALLIOPE_ADDR(0xA0080c)},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = CALLIOPE_ADDR(0xA01800)},
- .uart1_inten = {.phys = CALLIOPE_ADDR(0xA01804)},
- .uart1_config1 = {.phys = CALLIOPE_ADDR(0xA01808)},
- .uart1_config2 = {.phys = CALLIOPE_ADDR(0xA0180C)},
- .uart1_divisorhi = {.phys = CALLIOPE_ADDR(0xA01810)},
- .uart1_divisorlo = {.phys = CALLIOPE_ADDR(0xA01814)},
- .uart1_data = {.phys = CALLIOPE_ADDR(0xA01818)},
- .uart1_status = {.phys = CALLIOPE_ADDR(0xA0181C)},
-
- .int_stat_3 = {.phys = CALLIOPE_ADDR(0xA02800)},
- .int_stat_2 = {.phys = CALLIOPE_ADDR(0xA02804)},
- .int_stat_1 = {.phys = CALLIOPE_ADDR(0xA02808)},
- .int_stat_0 = {.phys = CALLIOPE_ADDR(0xA0280c)},
- .int_config = {.phys = CALLIOPE_ADDR(0xA02810)},
- .int_int_scan = {.phys = CALLIOPE_ADDR(0xA02818)},
- .ien_int_3 = {.phys = CALLIOPE_ADDR(0xA02830)},
- .ien_int_2 = {.phys = CALLIOPE_ADDR(0xA02834)},
- .ien_int_1 = {.phys = CALLIOPE_ADDR(0xA02838)},
- .ien_int_0 = {.phys = CALLIOPE_ADDR(0xA0283c)},
- .int_level_3_3 = {.phys = CALLIOPE_ADDR(0xA02880)},
- .int_level_3_2 = {.phys = CALLIOPE_ADDR(0xA02884)},
- .int_level_3_1 = {.phys = CALLIOPE_ADDR(0xA02888)},
- .int_level_3_0 = {.phys = CALLIOPE_ADDR(0xA0288c)},
- .int_level_2_3 = {.phys = CALLIOPE_ADDR(0xA02890)},
- .int_level_2_2 = {.phys = CALLIOPE_ADDR(0xA02894)},
- .int_level_2_1 = {.phys = CALLIOPE_ADDR(0xA02898)},
- .int_level_2_0 = {.phys = CALLIOPE_ADDR(0xA0289c)},
- .int_level_1_3 = {.phys = CALLIOPE_ADDR(0xA028a0)},
- .int_level_1_2 = {.phys = CALLIOPE_ADDR(0xA028a4)},
- .int_level_1_1 = {.phys = CALLIOPE_ADDR(0xA028a8)},
- .int_level_1_0 = {.phys = CALLIOPE_ADDR(0xA028ac)},
- .int_level_0_3 = {.phys = CALLIOPE_ADDR(0xA028b0)},
- .int_level_0_2 = {.phys = CALLIOPE_ADDR(0xA028b4)},
- .int_level_0_1 = {.phys = CALLIOPE_ADDR(0xA028b8)},
- .int_level_0_0 = {.phys = CALLIOPE_ADDR(0xA028bc)},
- .int_docsis_en = {.phys = CALLIOPE_ADDR(0xA028F4)},
-
- .mips_pll_setup = {.phys = CALLIOPE_ADDR(0x980000)},
- .fs432x4b4_usb_ctl = {.phys = CALLIOPE_ADDR(0x980030)},
- .test_bus = {.phys = CALLIOPE_ADDR(0x9800CC)},
- .crt_spare = {.phys = CALLIOPE_ADDR(0x9800d4)},
- .usb2_ohci_int_mask = {.phys = CALLIOPE_ADDR(0x9A000c)},
- .usb2_strap = {.phys = CALLIOPE_ADDR(0x9A0014)},
- .ehci_hcapbase = {.phys = CALLIOPE_ADDR(0x9BFE00)},
- .ohci_hc_revision = {.phys = CALLIOPE_ADDR(0x9BFC00)},
- .bcm1_bs_lmi_steer = {.phys = CALLIOPE_ADDR(0x9E0004)},
- .usb2_control = {.phys = CALLIOPE_ADDR(0x9E0054)},
- .usb2_stbus_obc = {.phys = CALLIOPE_ADDR(0x9BFF00)},
- .usb2_stbus_mess_size = {.phys = CALLIOPE_ADDR(0x9BFF04)},
- .usb2_stbus_chunk_size = {.phys = CALLIOPE_ADDR(0x9BFF08)},
-
- .pcie_regs = {.phys = 0x000000}, /* -doesn't exist- */
- .tim_ch = {.phys = CALLIOPE_ADDR(0xA02C10)},
- .tim_cl = {.phys = CALLIOPE_ADDR(0xA02C14)},
- .gpio_dout = {.phys = CALLIOPE_ADDR(0xA02c20)},
- .gpio_din = {.phys = CALLIOPE_ADDR(0xA02c24)},
- .gpio_dir = {.phys = CALLIOPE_ADDR(0xA02c2C)},
- .watchdog = {.phys = CALLIOPE_ADDR(0xA02c30)},
- .front_panel = {.phys = 0x000000}, /* -not used- */
-};
diff --git a/arch/mips/powertv/asic/asic-cronus.c b/arch/mips/powertv/asic/asic-cronus.c
deleted file mode 100644
index 7f8f3429b35..00000000000
--- a/arch/mips/powertv/asic/asic-cronus.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Cronus ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * Description: Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define CRONUS_ADDR(x) (CRONUS_IO_BASE + (x))
-
-const struct register_map cronus_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = CRONUS_ADDR(0x000000)},
- .eic_cfg_bits = {.phys = CRONUS_ADDR(0x000038)},
- .eic_ready_status = {.phys = CRONUS_ADDR(0x00004C)},
-
- .chipver3 = {.phys = CRONUS_ADDR(0x2A0800)},
- .chipver2 = {.phys = CRONUS_ADDR(0x2A0804)},
- .chipver1 = {.phys = CRONUS_ADDR(0x2A0808)},
- .chipver0 = {.phys = CRONUS_ADDR(0x2A080C)},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = CRONUS_ADDR(0x2A1800)},
- .uart1_inten = {.phys = CRONUS_ADDR(0x2A1804)},
- .uart1_config1 = {.phys = CRONUS_ADDR(0x2A1808)},
- .uart1_config2 = {.phys = CRONUS_ADDR(0x2A180C)},
- .uart1_divisorhi = {.phys = CRONUS_ADDR(0x2A1810)},
- .uart1_divisorlo = {.phys = CRONUS_ADDR(0x2A1814)},
- .uart1_data = {.phys = CRONUS_ADDR(0x2A1818)},
- .uart1_status = {.phys = CRONUS_ADDR(0x2A181C)},
-
- .int_stat_3 = {.phys = CRONUS_ADDR(0x2A2800)},
- .int_stat_2 = {.phys = CRONUS_ADDR(0x2A2804)},
- .int_stat_1 = {.phys = CRONUS_ADDR(0x2A2808)},
- .int_stat_0 = {.phys = CRONUS_ADDR(0x2A280C)},
- .int_config = {.phys = CRONUS_ADDR(0x2A2810)},
- .int_int_scan = {.phys = CRONUS_ADDR(0x2A2818)},
- .ien_int_3 = {.phys = CRONUS_ADDR(0x2A2830)},
- .ien_int_2 = {.phys = CRONUS_ADDR(0x2A2834)},
- .ien_int_1 = {.phys = CRONUS_ADDR(0x2A2838)},
- .ien_int_0 = {.phys = CRONUS_ADDR(0x2A283C)},
- .int_level_3_3 = {.phys = CRONUS_ADDR(0x2A2880)},
- .int_level_3_2 = {.phys = CRONUS_ADDR(0x2A2884)},
- .int_level_3_1 = {.phys = CRONUS_ADDR(0x2A2888)},
- .int_level_3_0 = {.phys = CRONUS_ADDR(0x2A288C)},
- .int_level_2_3 = {.phys = CRONUS_ADDR(0x2A2890)},
- .int_level_2_2 = {.phys = CRONUS_ADDR(0x2A2894)},
- .int_level_2_1 = {.phys = CRONUS_ADDR(0x2A2898)},
- .int_level_2_0 = {.phys = CRONUS_ADDR(0x2A289C)},
- .int_level_1_3 = {.phys = CRONUS_ADDR(0x2A28A0)},
- .int_level_1_2 = {.phys = CRONUS_ADDR(0x2A28A4)},
- .int_level_1_1 = {.phys = CRONUS_ADDR(0x2A28A8)},
- .int_level_1_0 = {.phys = CRONUS_ADDR(0x2A28AC)},
- .int_level_0_3 = {.phys = CRONUS_ADDR(0x2A28B0)},
- .int_level_0_2 = {.phys = CRONUS_ADDR(0x2A28B4)},
- .int_level_0_1 = {.phys = CRONUS_ADDR(0x2A28B8)},
- .int_level_0_0 = {.phys = CRONUS_ADDR(0x2A28BC)},
- .int_docsis_en = {.phys = CRONUS_ADDR(0x2A28F4)},
-
- .mips_pll_setup = {.phys = CRONUS_ADDR(0x1C0000)},
- .fs432x4b4_usb_ctl = {.phys = CRONUS_ADDR(0x1C0028)},
- .test_bus = {.phys = CRONUS_ADDR(0x1C00CC)},
- .crt_spare = {.phys = CRONUS_ADDR(0x1c00d4)},
- .usb2_ohci_int_mask = {.phys = CRONUS_ADDR(0x20000C)},
- .usb2_strap = {.phys = CRONUS_ADDR(0x200014)},
- .ehci_hcapbase = {.phys = CRONUS_ADDR(0x21FE00)},
- .ohci_hc_revision = {.phys = CRONUS_ADDR(0x21fc00)},
- .bcm1_bs_lmi_steer = {.phys = CRONUS_ADDR(0x2E0008)},
- .usb2_control = {.phys = CRONUS_ADDR(0x2E004C)},
- .usb2_stbus_obc = {.phys = CRONUS_ADDR(0x21FF00)},
- .usb2_stbus_mess_size = {.phys = CRONUS_ADDR(0x21FF04)},
- .usb2_stbus_chunk_size = {.phys = CRONUS_ADDR(0x21FF08)},
-
- .pcie_regs = {.phys = CRONUS_ADDR(0x220000)},
- .tim_ch = {.phys = CRONUS_ADDR(0x2A2C10)},
- .tim_cl = {.phys = CRONUS_ADDR(0x2A2C14)},
- .gpio_dout = {.phys = CRONUS_ADDR(0x2A2C20)},
- .gpio_din = {.phys = CRONUS_ADDR(0x2A2C24)},
- .gpio_dir = {.phys = CRONUS_ADDR(0x2A2C2C)},
- .watchdog = {.phys = CRONUS_ADDR(0x2A2C30)},
- .front_panel = {.phys = CRONUS_ADDR(0x2A3800)},
-};
diff --git a/arch/mips/powertv/asic/asic-gaia.c b/arch/mips/powertv/asic/asic-gaia.c
deleted file mode 100644
index 1265b49012e..00000000000
--- a/arch/mips/powertv/asic/asic-gaia.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Locations of devices in the Gaia ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: David VomLehn
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-const struct register_map gaia_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = GAIA_IO_BASE + 0x000000},
- .eic_cfg_bits = {.phys = GAIA_IO_BASE + 0x000038},
- .eic_ready_status = {.phys = GAIA_IO_BASE + 0x00004C},
-
- .chipver3 = {.phys = GAIA_IO_BASE + 0x2A0800},
- .chipver2 = {.phys = GAIA_IO_BASE + 0x2A0804},
- .chipver1 = {.phys = GAIA_IO_BASE + 0x2A0808},
- .chipver0 = {.phys = GAIA_IO_BASE + 0x2A080C},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = GAIA_IO_BASE + 0x2A1800},
- .uart1_inten = {.phys = GAIA_IO_BASE + 0x2A1804},
- .uart1_config1 = {.phys = GAIA_IO_BASE + 0x2A1808},
- .uart1_config2 = {.phys = GAIA_IO_BASE + 0x2A180C},
- .uart1_divisorhi = {.phys = GAIA_IO_BASE + 0x2A1810},
- .uart1_divisorlo = {.phys = GAIA_IO_BASE + 0x2A1814},
- .uart1_data = {.phys = GAIA_IO_BASE + 0x2A1818},
- .uart1_status = {.phys = GAIA_IO_BASE + 0x2A181C},
-
- .int_stat_3 = {.phys = GAIA_IO_BASE + 0x2A2800},
- .int_stat_2 = {.phys = GAIA_IO_BASE + 0x2A2804},
- .int_stat_1 = {.phys = GAIA_IO_BASE + 0x2A2808},
- .int_stat_0 = {.phys = GAIA_IO_BASE + 0x2A280C},
- .int_config = {.phys = GAIA_IO_BASE + 0x2A2810},
- .int_int_scan = {.phys = GAIA_IO_BASE + 0x2A2818},
- .ien_int_3 = {.phys = GAIA_IO_BASE + 0x2A2830},
- .ien_int_2 = {.phys = GAIA_IO_BASE + 0x2A2834},
- .ien_int_1 = {.phys = GAIA_IO_BASE + 0x2A2838},
- .ien_int_0 = {.phys = GAIA_IO_BASE + 0x2A283C},
- .int_level_3_3 = {.phys = GAIA_IO_BASE + 0x2A2880},
- .int_level_3_2 = {.phys = GAIA_IO_BASE + 0x2A2884},
- .int_level_3_1 = {.phys = GAIA_IO_BASE + 0x2A2888},
- .int_level_3_0 = {.phys = GAIA_IO_BASE + 0x2A288C},
- .int_level_2_3 = {.phys = GAIA_IO_BASE + 0x2A2890},
- .int_level_2_2 = {.phys = GAIA_IO_BASE + 0x2A2894},
- .int_level_2_1 = {.phys = GAIA_IO_BASE + 0x2A2898},
- .int_level_2_0 = {.phys = GAIA_IO_BASE + 0x2A289C},
- .int_level_1_3 = {.phys = GAIA_IO_BASE + 0x2A28A0},
- .int_level_1_2 = {.phys = GAIA_IO_BASE + 0x2A28A4},
- .int_level_1_1 = {.phys = GAIA_IO_BASE + 0x2A28A8},
- .int_level_1_0 = {.phys = GAIA_IO_BASE + 0x2A28AC},
- .int_level_0_3 = {.phys = GAIA_IO_BASE + 0x2A28B0},
- .int_level_0_2 = {.phys = GAIA_IO_BASE + 0x2A28B4},
- .int_level_0_1 = {.phys = GAIA_IO_BASE + 0x2A28B8},
- .int_level_0_0 = {.phys = GAIA_IO_BASE + 0x2A28BC},
- .int_docsis_en = {.phys = GAIA_IO_BASE + 0x2A28F4},
-
- .mips_pll_setup = {.phys = GAIA_IO_BASE + 0x1C0000},
- .fs432x4b4_usb_ctl = {.phys = GAIA_IO_BASE + 0x1C0024},
- .test_bus = {.phys = GAIA_IO_BASE + 0x1C00CC},
- .crt_spare = {.phys = GAIA_IO_BASE + 0x1c0108},
- .usb2_ohci_int_mask = {.phys = GAIA_IO_BASE + 0x20000C},
- .usb2_strap = {.phys = GAIA_IO_BASE + 0x200014},
- .ehci_hcapbase = {.phys = GAIA_IO_BASE + 0x21FE00},
- .ohci_hc_revision = {.phys = GAIA_IO_BASE + 0x21fc00},
- .bcm1_bs_lmi_steer = {.phys = GAIA_IO_BASE + 0x2E0004},
- .usb2_control = {.phys = GAIA_IO_BASE + 0x2E004C},
- .usb2_stbus_obc = {.phys = GAIA_IO_BASE + 0x21FF00},
- .usb2_stbus_mess_size = {.phys = GAIA_IO_BASE + 0x21FF04},
- .usb2_stbus_chunk_size = {.phys = GAIA_IO_BASE + 0x21FF08},
-
- .pcie_regs = {.phys = GAIA_IO_BASE + 0x220000},
- .tim_ch = {.phys = GAIA_IO_BASE + 0x2A2C10},
- .tim_cl = {.phys = GAIA_IO_BASE + 0x2A2C14},
- .gpio_dout = {.phys = GAIA_IO_BASE + 0x2A2C20},
- .gpio_din = {.phys = GAIA_IO_BASE + 0x2A2C24},
- .gpio_dir = {.phys = GAIA_IO_BASE + 0x2A2C2C},
- .watchdog = {.phys = GAIA_IO_BASE + 0x2A2C30},
- .front_panel = {.phys = GAIA_IO_BASE + 0x2A3800},
-};
diff --git a/arch/mips/powertv/asic/asic-zeus.c b/arch/mips/powertv/asic/asic-zeus.c
deleted file mode 100644
index 14e7de137e0..00000000000
--- a/arch/mips/powertv/asic/asic-zeus.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Zeus ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * Description: Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define ZEUS_ADDR(x) (ZEUS_IO_BASE + (x))
-
-const struct register_map zeus_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = ZEUS_ADDR(0x000000)},
- .eic_cfg_bits = {.phys = ZEUS_ADDR(0x000038)},
- .eic_ready_status = {.phys = ZEUS_ADDR(0x00004c)},
-
- .chipver3 = {.phys = ZEUS_ADDR(0x280800)},
- .chipver2 = {.phys = ZEUS_ADDR(0x280804)},
- .chipver1 = {.phys = ZEUS_ADDR(0x280808)},
- .chipver0 = {.phys = ZEUS_ADDR(0x28080c)},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = ZEUS_ADDR(0x281800)},
- .uart1_inten = {.phys = ZEUS_ADDR(0x281804)},
- .uart1_config1 = {.phys = ZEUS_ADDR(0x281808)},
- .uart1_config2 = {.phys = ZEUS_ADDR(0x28180C)},
- .uart1_divisorhi = {.phys = ZEUS_ADDR(0x281810)},
- .uart1_divisorlo = {.phys = ZEUS_ADDR(0x281814)},
- .uart1_data = {.phys = ZEUS_ADDR(0x281818)},
- .uart1_status = {.phys = ZEUS_ADDR(0x28181C)},
-
- .int_stat_3 = {.phys = ZEUS_ADDR(0x282800)},
- .int_stat_2 = {.phys = ZEUS_ADDR(0x282804)},
- .int_stat_1 = {.phys = ZEUS_ADDR(0x282808)},
- .int_stat_0 = {.phys = ZEUS_ADDR(0x28280c)},
- .int_config = {.phys = ZEUS_ADDR(0x282810)},
- .int_int_scan = {.phys = ZEUS_ADDR(0x282818)},
- .ien_int_3 = {.phys = ZEUS_ADDR(0x282830)},
- .ien_int_2 = {.phys = ZEUS_ADDR(0x282834)},
- .ien_int_1 = {.phys = ZEUS_ADDR(0x282838)},
- .ien_int_0 = {.phys = ZEUS_ADDR(0x28283c)},
- .int_level_3_3 = {.phys = ZEUS_ADDR(0x282880)},
- .int_level_3_2 = {.phys = ZEUS_ADDR(0x282884)},
- .int_level_3_1 = {.phys = ZEUS_ADDR(0x282888)},
- .int_level_3_0 = {.phys = ZEUS_ADDR(0x28288c)},
- .int_level_2_3 = {.phys = ZEUS_ADDR(0x282890)},
- .int_level_2_2 = {.phys = ZEUS_ADDR(0x282894)},
- .int_level_2_1 = {.phys = ZEUS_ADDR(0x282898)},
- .int_level_2_0 = {.phys = ZEUS_ADDR(0x28289c)},
- .int_level_1_3 = {.phys = ZEUS_ADDR(0x2828a0)},
- .int_level_1_2 = {.phys = ZEUS_ADDR(0x2828a4)},
- .int_level_1_1 = {.phys = ZEUS_ADDR(0x2828a8)},
- .int_level_1_0 = {.phys = ZEUS_ADDR(0x2828ac)},
- .int_level_0_3 = {.phys = ZEUS_ADDR(0x2828b0)},
- .int_level_0_2 = {.phys = ZEUS_ADDR(0x2828b4)},
- .int_level_0_1 = {.phys = ZEUS_ADDR(0x2828b8)},
- .int_level_0_0 = {.phys = ZEUS_ADDR(0x2828bc)},
- .int_docsis_en = {.phys = ZEUS_ADDR(0x2828F4)},
-
- .mips_pll_setup = {.phys = ZEUS_ADDR(0x1a0000)},
- .fs432x4b4_usb_ctl = {.phys = ZEUS_ADDR(0x1a0018)},
- .test_bus = {.phys = ZEUS_ADDR(0x1a0238)},
- .crt_spare = {.phys = ZEUS_ADDR(0x1a0090)},
- .usb2_ohci_int_mask = {.phys = ZEUS_ADDR(0x1e000c)},
- .usb2_strap = {.phys = ZEUS_ADDR(0x1e0014)},
- .ehci_hcapbase = {.phys = ZEUS_ADDR(0x1FFE00)},
- .ohci_hc_revision = {.phys = ZEUS_ADDR(0x1FFC00)},
- .bcm1_bs_lmi_steer = {.phys = ZEUS_ADDR(0x2C0008)},
- .usb2_control = {.phys = ZEUS_ADDR(0x2c01a0)},
- .usb2_stbus_obc = {.phys = ZEUS_ADDR(0x1FFF00)},
- .usb2_stbus_mess_size = {.phys = ZEUS_ADDR(0x1FFF04)},
- .usb2_stbus_chunk_size = {.phys = ZEUS_ADDR(0x1FFF08)},
-
- .pcie_regs = {.phys = ZEUS_ADDR(0x200000)},
- .tim_ch = {.phys = ZEUS_ADDR(0x282C10)},
- .tim_cl = {.phys = ZEUS_ADDR(0x282C14)},
- .gpio_dout = {.phys = ZEUS_ADDR(0x282c20)},
- .gpio_din = {.phys = ZEUS_ADDR(0x282c24)},
- .gpio_dir = {.phys = ZEUS_ADDR(0x282c2C)},
- .watchdog = {.phys = ZEUS_ADDR(0x282c30)},
- .front_panel = {.phys = ZEUS_ADDR(0x283800)},
-};
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
deleted file mode 100644
index 8380605d597..00000000000
--- a/arch/mips/powertv/asic/asic_devices.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- *
- * Description: Defines the platform resources for Gaia-based settops.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/resource.h>
-#include <linux/serial_reg.h>
-#include <linux/io.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <asm/page.h>
-#include <linux/swap.h>
-#include <linux/highmem.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/asic_regs.h>
-#include <asm/mach-powertv/interrupts.h>
-
-#ifdef CONFIG_BOOTLOADER_DRIVER
-#include <asm/mach-powertv/kbldr.h>
-#endif
-#include <asm/bootinfo.h>
-
-#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
-
-/*
- * Forward Prototypes
- */
-static void pmem_setup_resource(void);
-
-/*
- * Global Variables
- */
-enum asic_type asic;
-
-unsigned int platform_features;
-unsigned int platform_family;
-struct register_map _asic_register_map;
-EXPORT_SYMBOL(_asic_register_map); /* Exported for testing */
-unsigned long asic_phy_base;
-unsigned long asic_base;
-EXPORT_SYMBOL(asic_base); /* Exported for testing */
-struct resource *gp_resources;
-
-/*
- * Don't recommend to use it directly, it is usually used by kernel internally.
- * Portable code should be using interfaces such as ioremp, dma_map_single, etc.
- */
-unsigned long phys_to_dma_offset;
-EXPORT_SYMBOL(phys_to_dma_offset);
-
-/*
- *
- * IO Resource Definition
- *
- */
-
-struct resource asic_resource = {
- .name = "ASIC Resource",
- .start = 0,
- .end = ASIC_IO_SIZE,
- .flags = IORESOURCE_MEM,
-};
-
-/*
- * Allow override of bootloader-specified model
- * Returns zero on success, a negative errno value on failure. This parameter
- * allows overriding of the bootloader-specified model.
- */
-static char __initdata cmdline[COMMAND_LINE_SIZE];
-
-#define FORCEFAMILY_PARAM "forcefamily"
-
-/*
- * check_forcefamily - check for, and parse, forcefamily command line parameter
- * @forced_family: Pointer to two-character array in which to store the
- * value of the forcedfamily parameter, if any.
- */
-static __init int check_forcefamily(unsigned char forced_family[2])
-{
- const char *p;
-
- forced_family[0] = '\0';
- forced_family[1] = '\0';
-
- /* Check the command line for a forcefamily directive */
- strncpy(cmdline, arcs_cmdline, COMMAND_LINE_SIZE - 1);
- p = strstr(cmdline, FORCEFAMILY_PARAM);
- if (p && (p != cmdline) && (*(p - 1) != ' '))
- p = strstr(p, " " FORCEFAMILY_PARAM "=");
-
- if (p) {
- p += strlen(FORCEFAMILY_PARAM "=");
-
- if (*p == '\0' || *(p + 1) == '\0' ||
- (*(p + 2) != '\0' && *(p + 2) != ' '))
- pr_err(FORCEFAMILY_PARAM " must be exactly two "
- "characters long, ignoring value\n");
-
- else {
- forced_family[0] = *p;
- forced_family[1] = *(p + 1);
- }
- }
-
- return 0;
-}
-
-/*
- * platform_set_family - determine major platform family type.
- *
- * Returns family type; -1 if none
- * Returns the family type; -1 if none
- *
- */
-static __init noinline void platform_set_family(void)
-{
- unsigned char forced_family[2];
- unsigned short bootldr_family;
-
- if (check_forcefamily(forced_family) == 0)
- bootldr_family = BOOTLDRFAMILY(forced_family[0],
- forced_family[1]);
- else
- bootldr_family = (unsigned short) BOOTLDRFAMILY(
- CONFIG_BOOTLOADER_FAMILY[0],
- CONFIG_BOOTLOADER_FAMILY[1]);
-
- pr_info("Bootloader Family = 0x%04X\n", bootldr_family);
-
- switch (bootldr_family) {
- case BOOTLDRFAMILY('R', '1'):
- platform_family = FAMILY_1500;
- break;
- case BOOTLDRFAMILY('4', '4'):
- platform_family = FAMILY_4500;
- break;
- case BOOTLDRFAMILY('4', '6'):
- platform_family = FAMILY_4600;
- break;
- case BOOTLDRFAMILY('A', '1'):
- platform_family = FAMILY_4600VZA;
- break;
- case BOOTLDRFAMILY('8', '5'):
- platform_family = FAMILY_8500;
- break;
- case BOOTLDRFAMILY('R', '2'):
- platform_family = FAMILY_8500RNG;
- break;
- case BOOTLDRFAMILY('8', '6'):
- platform_family = FAMILY_8600;
- break;
- case BOOTLDRFAMILY('B', '1'):
- platform_family = FAMILY_8600VZB;
- break;
- case BOOTLDRFAMILY('E', '1'):
- platform_family = FAMILY_1500VZE;
- break;
- case BOOTLDRFAMILY('F', '1'):
- platform_family = FAMILY_1500VZF;
- break;
- case BOOTLDRFAMILY('8', '7'):
- platform_family = FAMILY_8700;
- break;
- default:
- platform_family = -1;
- }
-}
-
-unsigned int platform_get_family(void)
-{
- return platform_family;
-}
-EXPORT_SYMBOL(platform_get_family);
-
-/*
- * platform_get_asic - determine the ASIC type.
- *
- * Returns the ASIC type, or ASIC_UNKNOWN if unknown
- *
- */
-enum asic_type platform_get_asic(void)
-{
- return asic;
-}
-EXPORT_SYMBOL(platform_get_asic);
-
-/*
- * set_register_map - set ASIC register configuration
- * @phys_base: Physical address of the base of the ASIC registers
- * @map: Description of key ASIC registers
- */
-static void __init set_register_map(unsigned long phys_base,
- const struct register_map *map)
-{
- asic_phy_base = phys_base;
- _asic_register_map = *map;
- register_map_virtualize(&_asic_register_map);
- asic_base = (unsigned long)ioremap_nocache(phys_base, ASIC_IO_SIZE);
-}
-
-/**
- * configure_platform - configuration based on platform type.
- */
-void __init configure_platform(void)
-{
- platform_set_family();
-
- switch (platform_family) {
- case FAMILY_1500:
- case FAMILY_1500VZE:
- case FAMILY_1500VZF:
- platform_features = FFS_CAPABLE;
- asic = ASIC_CALLIOPE;
- set_register_map(CALLIOPE_IO_BASE, &calliope_register_map);
-
- if (platform_family == FAMILY_1500VZE) {
- gp_resources = non_dvr_vze_calliope_resources;
- pr_info("Platform: 1500/Vz Class E - "
- "CALLIOPE, NON_DVR_CAPABLE\n");
- } else if (platform_family == FAMILY_1500VZF) {
- gp_resources = non_dvr_vzf_calliope_resources;
- pr_info("Platform: 1500/Vz Class F - "
- "CALLIOPE, NON_DVR_CAPABLE\n");
- } else {
- gp_resources = non_dvr_calliope_resources;
- pr_info("Platform: 1500/RNG100 - CALLIOPE, "
- "NON_DVR_CAPABLE\n");
- }
- break;
-
- case FAMILY_4500:
- platform_features = FFS_CAPABLE | PCIE_CAPABLE |
- DISPLAY_CAPABLE;
- asic = ASIC_ZEUS;
- set_register_map(ZEUS_IO_BASE, &zeus_register_map);
- gp_resources = non_dvr_zeus_resources;
-
- pr_info("Platform: 4500 - ZEUS, NON_DVR_CAPABLE\n");
- break;
-
- case FAMILY_4600:
- {
- unsigned int chipversion = 0;
-
- /* The settop has PCIE but it isn't used, so don't advertise
- * it*/
- platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
-
- /* Cronus and Cronus Lite have the same register map */
- set_register_map(CRONUS_IO_BASE, &cronus_register_map);
-
- /* ASIC version will determine if this is a real CronusLite or
- * Castrati(Cronus) */
- chipversion = asic_read(chipver3) << 24;
- chipversion |= asic_read(chipver2) << 16;
- chipversion |= asic_read(chipver1) << 8;
- chipversion |= asic_read(chipver0);
-
- if ((chipversion == CRONUS_10) || (chipversion == CRONUS_11))
- asic = ASIC_CRONUS;
- else
- asic = ASIC_CRONUSLITE;
-
- gp_resources = non_dvr_cronuslite_resources;
- pr_info("Platform: 4600 - %s, NON_DVR_CAPABLE, "
- "chipversion=0x%08X\n",
- (asic == ASIC_CRONUS) ? "CRONUS" : "CRONUS LITE",
- chipversion);
- break;
- }
- case FAMILY_4600VZA:
- platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
- asic = ASIC_CRONUS;
- set_register_map(CRONUS_IO_BASE, &cronus_register_map);
- gp_resources = non_dvr_cronus_resources;
-
- pr_info("Platform: Vz Class A - CRONUS, NON_DVR_CAPABLE\n");
- break;
-
- case FAMILY_8500:
- case FAMILY_8500RNG:
- platform_features = DVR_CAPABLE | PCIE_CAPABLE |
- DISPLAY_CAPABLE;
- asic = ASIC_ZEUS;
- set_register_map(ZEUS_IO_BASE, &zeus_register_map);
- gp_resources = dvr_zeus_resources;
-
- pr_info("Platform: 8500/RNG200 - ZEUS, DVR_CAPABLE\n");
- break;
-
- case FAMILY_8600:
- case FAMILY_8600VZB:
- platform_features = DVR_CAPABLE | PCIE_CAPABLE |
- DISPLAY_CAPABLE;
- asic = ASIC_CRONUS;
- set_register_map(CRONUS_IO_BASE, &cronus_register_map);
- gp_resources = dvr_cronus_resources;
-
- pr_info("Platform: 8600/Vz Class B - CRONUS, "
- "DVR_CAPABLE\n");
- break;
-
- case FAMILY_8700:
- platform_features = FFS_CAPABLE | PCIE_CAPABLE;
- asic = ASIC_GAIA;
- set_register_map(GAIA_IO_BASE, &gaia_register_map);
- gp_resources = dvr_gaia_resources;
-
- pr_info("Platform: 8700 - GAIA, DVR_CAPABLE\n");
- break;
-
- default:
- pr_crit("Platform: UNKNOWN PLATFORM\n");
- break;
- }
-
- switch (asic) {
- case ASIC_ZEUS:
- phys_to_dma_offset = 0x30000000;
- break;
- case ASIC_CALLIOPE:
- phys_to_dma_offset = 0x10000000;
- break;
- case ASIC_CRONUSLITE:
- /* Fall through */
- case ASIC_CRONUS:
- /*
- * TODO: We suppose 0x10000000 aliases into 0x20000000-
- * 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000-
- * 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000.
- */
- phys_to_dma_offset = 0x10000000;
- break;
- default:
- phys_to_dma_offset = 0x00000000;
- break;
- }
-}
-
-/*
- * RESOURCE ALLOCATION
- *
- */
-/*
- * Allocates/reserves the Platform memory resources early in the boot process.
- * This ignores any resources that are designated IORESOURCE_IO
- */
-void __init platform_alloc_bootmem(void)
-{
- int i;
- int total = 0;
-
- /* Get persistent memory data from command line before allocating
- * resources. This need to happen before normal command line parsing
- * has been done */
- pmem_setup_resource();
-
- /* Loop through looking for resources that want a particular address */
- for (i = 0; gp_resources[i].flags != 0; i++) {
- int size = resource_size(&gp_resources[i]);
- if ((gp_resources[i].start != 0) &&
- ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
- reserve_bootmem(dma_to_phys(gp_resources[i].start),
- size, 0);
- total += resource_size(&gp_resources[i]);
- pr_info("reserve resource %s at %08x (%u bytes)\n",
- gp_resources[i].name, gp_resources[i].start,
- resource_size(&gp_resources[i]));
- }
- }
-
- /* Loop through assigning addresses for those that are left */
- for (i = 0; gp_resources[i].flags != 0; i++) {
- int size = resource_size(&gp_resources[i]);
- if ((gp_resources[i].start == 0) &&
- ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
- void *mem = alloc_bootmem_pages(size);
-
- if (mem == NULL)
- pr_err("Unable to allocate bootmem pages "
- "for %s\n", gp_resources[i].name);
-
- else {
- gp_resources[i].start =
- phys_to_dma(virt_to_phys(mem));
- gp_resources[i].end =
- gp_resources[i].start + size - 1;
- total += size;
- pr_info("allocate resource %s at %08x "
- "(%u bytes)\n",
- gp_resources[i].name,
- gp_resources[i].start, size);
- }
- }
- }
-
- pr_info("Total Platform driver memory allocation: 0x%08x\n", total);
-
- /* indicate resources that are platform I/O related */
- for (i = 0; gp_resources[i].flags != 0; i++) {
- if ((gp_resources[i].start != 0) &&
- ((gp_resources[i].flags & IORESOURCE_IO) != 0)) {
- pr_info("reserved platform resource %s at %08x\n",
- gp_resources[i].name, gp_resources[i].start);
- }
- }
-}
-
-/*
- *
- * PERSISTENT MEMORY (PMEM) CONFIGURATION
- *
- */
-static unsigned long pmemaddr __initdata;
-
-static int __init early_param_pmemaddr(char *p)
-{
- pmemaddr = (unsigned long)simple_strtoul(p, NULL, 0);
- return 0;
-}
-early_param("pmemaddr", early_param_pmemaddr);
-
-static long pmemlen __initdata;
-
-static int __init early_param_pmemlen(char *p)
-{
-/* TODO: we can use this code when and if the bootloader ever changes this */
-#if 0
- pmemlen = (unsigned long)simple_strtoul(p, NULL, 0);
-#else
- pmemlen = 0x20000;
-#endif
- return 0;
-}
-early_param("pmemlen", early_param_pmemlen);
-
-/*
- * Set up persistent memory. If we were given values, we patch the array of
- * resources. Otherwise, persistent memory may be allocated anywhere at all.
- */
-static void __init pmem_setup_resource(void)
-{
- struct resource *resource;
- resource = asic_resource_get("DiagPersistentMemory");
-
- if (resource && pmemaddr && pmemlen) {
- /* The address provided by bootloader is in kseg0. Convert to
- * a bus address. */
- resource->start = phys_to_dma(pmemaddr - 0x80000000);
- resource->end = resource->start + pmemlen - 1;
-
- pr_info("persistent memory: start=0x%x end=0x%x\n",
- resource->start, resource->end);
- }
-}
-
-/*
- *
- * RESOURCE ACCESS FUNCTIONS
- *
- */
-
-/**
- * asic_resource_get - retrieves parameters for a platform resource.
- * @name: string to match resource
- *
- * Returns a pointer to a struct resource corresponding to the given name.
- *
- * CANNOT BE NAMED platform_resource_get, which would be the obvious choice,
- * as this function name is already declared
- */
-struct resource *asic_resource_get(const char *name)
-{
- int i;
-
- for (i = 0; gp_resources[i].flags != 0; i++) {
- if (strcmp(gp_resources[i].name, name) == 0)
- return &gp_resources[i];
- }
-
- return NULL;
-}
-EXPORT_SYMBOL(asic_resource_get);
-
-/**
- * platform_release_memory - release pre-allocated memory
- * @ptr: pointer to memory to release
- * @size: size of resource
- *
- * This must only be called for memory allocated or reserved via the boot
- * memory allocator.
- */
-void platform_release_memory(void *ptr, int size)
-{
- free_reserved_area(ptr, ptr + size, -1, NULL);
-}
-EXPORT_SYMBOL(platform_release_memory);
-
-/*
- *
- * FEATURE AVAILABILITY FUNCTIONS
- *
- */
-int platform_supports_dvr(void)
-{
- return (platform_features & DVR_CAPABLE) != 0;
-}
-
-int platform_supports_ffs(void)
-{
- return (platform_features & FFS_CAPABLE) != 0;
-}
-
-int platform_supports_pcie(void)
-{
- return (platform_features & PCIE_CAPABLE) != 0;
-}
-
-int platform_supports_display(void)
-{
- return (platform_features & DISPLAY_CAPABLE) != 0;
-}
diff --git a/arch/mips/powertv/asic/asic_int.c b/arch/mips/powertv/asic/asic_int.c
deleted file mode 100644
index f44cd9295ca..00000000000
--- a/arch/mips/powertv/asic/asic_int.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
- * Copyright (C) 2001 Ralf Baechle
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines for generic manipulation of the interrupts found on the PowerTV
- * platform.
- *
- * The interrupt controller is located in the South Bridge a PIIX4 device
- * with two internal 82C95 interrupt controllers.
- */
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/kernel.h>
-#include <linux/random.h>
-
-#include <asm/irq_cpu.h>
-#include <linux/io.h>
-#include <asm/irq_regs.h>
-#include <asm/setup.h>
-#include <asm/mips-boards/generic.h>
-
-#include <asm/mach-powertv/asic_regs.h>
-
-static DEFINE_RAW_SPINLOCK(asic_irq_lock);
-
-static inline int get_int(void)
-{
- unsigned long flags;
- int irq;
-
- raw_spin_lock_irqsave(&asic_irq_lock, flags);
-
- irq = (asic_read(int_int_scan) >> 4) - 1;
-
- if (irq == 0 || irq >= NR_IRQS)
- irq = -1;
-
- raw_spin_unlock_irqrestore(&asic_irq_lock, flags);
-
- return irq;
-}
-
-static void asic_irqdispatch(void)
-{
- int irq;
-
- irq = get_int();
- if (irq < 0)
- return; /* interrupt has already been cleared */
-
- do_IRQ(irq);
-}
-
-static inline int clz(unsigned long x)
-{
- __asm__(
- " .set push \n"
- " .set mips32 \n"
- " clz %0, %1 \n"
- " .set pop \n"
- : "=r" (x)
- : "r" (x));
-
- return x;
-}
-
-/*
- * Version of ffs that only looks at bits 12..15.
- */
-static inline unsigned int irq_ffs(unsigned int pending)
-{
- return fls(pending) - 1 + CAUSEB_IP;
-}
-
-/*
- * TODO: check how it works under EIC mode.
- */
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
- int irq;
-
- irq = irq_ffs(pending);
-
- if (irq == CAUSEF_IP3)
- asic_irqdispatch();
- else if (irq >= 0)
- do_IRQ(irq);
- else
- spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
- int i;
-
- asic_irq_init();
-
- /*
- * Initialize interrupt exception vectors.
- */
- if (cpu_has_veic || cpu_has_vint) {
- int nvec = cpu_has_veic ? 64 : 8;
- for (i = 0; i < nvec; i++)
- set_vi_handler(i, asic_irqdispatch);
- }
-}
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
deleted file mode 100644
index 9344902dc58..00000000000
--- a/arch/mips/powertv/asic/irq_asic.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Portions copyright (C) 2005-2009 Scientific Atlanta
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * Modified from arch/mips/kernel/irq-rm7000.c:
- * Copyright (C) 2003 Ralf Baechle
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-
-#include <asm/mach-powertv/asic_regs.h>
-
-static inline void unmask_asic_irq(struct irq_data *d)
-{
- unsigned long enable_bit;
- unsigned int irq = d->irq;
-
- enable_bit = (1 << (irq & 0x1f));
-
- switch (irq >> 5) {
- case 0:
- asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
- break;
- case 1:
- asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
- break;
- case 2:
- asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
- break;
- case 3:
- asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
- break;
- default:
- BUG();
- }
-}
-
-static inline void mask_asic_irq(struct irq_data *d)
-{
- unsigned long disable_mask;
- unsigned int irq = d->irq;
-
- disable_mask = ~(1 << (irq & 0x1f));
-
- switch (irq >> 5) {
- case 0:
- asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
- break;
- case 1:
- asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
- break;
- case 2:
- asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
- break;
- case 3:
- asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
- break;
- default:
- BUG();
- }
-}
-
-static struct irq_chip asic_irq_chip = {
- .name = "ASIC Level",
- .irq_mask = mask_asic_irq,
- .irq_unmask = unmask_asic_irq,
-};
-
-void __init asic_irq_init(void)
-{
- int i;
-
- /* set priority to 0 */
- write_c0_status(read_c0_status() & ~(0x0000fc00));
-
- asic_write(0, ien_int_0);
- asic_write(0, ien_int_1);
- asic_write(0, ien_int_2);
- asic_write(0, ien_int_3);
-
- asic_write(0x0fffffff, int_level_3_3);
- asic_write(0xffffffff, int_level_3_2);
- asic_write(0xffffffff, int_level_3_1);
- asic_write(0xffffffff, int_level_3_0);
- asic_write(0xffffffff, int_level_2_3);
- asic_write(0xffffffff, int_level_2_2);
- asic_write(0xffffffff, int_level_2_1);
- asic_write(0xffffffff, int_level_2_0);
- asic_write(0xffffffff, int_level_1_3);
- asic_write(0xffffffff, int_level_1_2);
- asic_write(0xffffffff, int_level_1_1);
- asic_write(0xffffffff, int_level_1_0);
- asic_write(0xffffffff, int_level_0_3);
- asic_write(0xffffffff, int_level_0_2);
- asic_write(0xffffffff, int_level_0_1);
- asic_write(0xffffffff, int_level_0_0);
-
- asic_write(0xf, int_int_scan);
-
- /*
- * Initialize interrupt handlers.
- */
- for (i = 0; i < NR_IRQS; i++)
- irq_set_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
-}
diff --git a/arch/mips/powertv/asic/prealloc-calliope.c b/arch/mips/powertv/asic/prealloc-calliope.c
deleted file mode 100644
index 98dc5165057..00000000000
--- a/arch/mips/powertv/asic/prealloc-calliope.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Memory pre-allocations for Calliope boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * NON_DVR_CAPABLE CALLIOPE RESOURCES
- */
-struct resource non_dvr_calliope_resources[] __initdata =
-{
- /*
- * VIDEO / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~36.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26700000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 6MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x27500000, 0x27c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x26700000, 0x26700000+(14*1048576)-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x23700000, 0x23720000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Synopsys GMAC Memory Region
- */
- /* 64KiB */
- PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-
-struct resource non_dvr_vze_calliope_resources[] __initdata =
-{
- /*
- * VIDEO / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x22000000, 0x22200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x22200000, 0x22202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (10.12MiB) */
- PREALLOC_NORMAL("MediaMemory1", 0x22202000, 0x22C20B85-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 3.125MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x20396000, 0x206B6000-1,
- IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (2.59MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x20100000, 0x20396000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x206B6000, 0x206D6000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Synopsys GMAC Memory Region
- */
- /* 64KiB */
- PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-struct resource non_dvr_vzf_calliope_resources[] __initdata =
-{
- /*
- * VIDEO / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~19.4 (21.5MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x25580000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 4.5MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00480000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x25600000, 0x25600000+(14*1048576)-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x23700000, 0x23720000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Synopsys GMAC Memory Region
- */
- /* 64KiB */
- PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc-cronus.c b/arch/mips/powertv/asic/prealloc-cronus.c
deleted file mode 100644
index 7c6ce759693..00000000000
--- a/arch/mips/powertv/asic/prealloc-cronus.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Memory pre-allocations for Cronus boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * DVR_CAPABLE CRONUS RESOURCES
- */
-struct resource dvr_cronus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26000000-1,
- IORESOURCE_MEM)
-
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 2 image (2MiB) */
- PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x60200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 monitor (8KiB) */
- PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x62000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 12MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
- IORESOURCE_MEM)
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer
- */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x002EA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * ITFS
- */
- /* 815,104 bytes each for 2 ITFS partitions. */
- PREALLOC_NORMAL("ITFS", 0x00000000, 0x0018E000-1, IORESOURCE_MEM)
-
- /*
- * AVFS
- */
- /* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x007c2000-1,
- IORESOURCE_MEM)
-
- /* 4KiB */
- PREALLOC_NORMAL("AvfsFileSys", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- IORESOURCE_MEM)
-
- /*
- * KAVNET
- */
- /* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
- PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
- IORESOURCE_MEM)
- /* NP Image - must be video bank 1 (320KiB) */
- PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
- /* NP IPC - must be video bank 2 (512KiB) */
- PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-/*
- * NON_DVR_CAPABLE CRONUS RESOURCES
- */
-struct resource non_dvr_cronus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26000000-1,
- IORESOURCE_MEM)
-
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 2 image (2MiB) */
- PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x60200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 monitor (8KiB) */
- PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x62000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 12MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
- IORESOURCE_MEM)
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1, IORESOURCE_MEM)
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1, IORESOURCE_MEM)
-
- /*
- * KAVNET
- */
- /* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
- PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
- IORESOURCE_MEM)
- /* NP Image - must be video bank 1 (320KiB) */
- PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
- /* NP IPC - must be video bank 2 (512KiB) */
- PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc-cronuslite.c b/arch/mips/powertv/asic/prealloc-cronuslite.c
deleted file mode 100644
index a7937ba7b4c..00000000000
--- a/arch/mips/powertv/asic/prealloc-cronuslite.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Memory pre-allocations for Cronus Lite boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * NON_DVR_CAPABLE CRONUSLITE RESOURCES
- */
-struct resource non_dvr_cronuslite_resources[] __initdata =
-{
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x60000000, 0x60200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x60200000, 0x60202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x60202000, 0x62000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 6MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
- IORESOURCE_MEM)
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1, IORESOURCE_MEM)
-
- /*
- * KAVNET
- */
- /* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
- PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
- IORESOURCE_MEM)
- /* NP Image - must be video bank 1 (320KiB) */
- PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
- /* NP IPC - must be video bank 2 (512KiB) */
- PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc-gaia.c b/arch/mips/powertv/asic/prealloc-gaia.c
deleted file mode 100644
index 2303bbfe6b8..00000000000
--- a/arch/mips/powertv/asic/prealloc-gaia.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- * Memory pre-allocations for Gaia boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: David VomLehn
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-/*
- * DVR_CAPABLE GAIA RESOURCES
- */
-struct resource dvr_gaia_resources[] __initdata = {
- /*
- *
- * VIDEO1 / LX1
- *
- */
- {
- .name = "ST231aImage", /* Delta-Mu 1 image and ram */
- .start = 0x24000000,
- .end = 0x241FFFFF, /* 2MiB */
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ST231aMonitor", /* 8KiB block ST231a monitor */
- .start = 0x24200000,
- .end = 0x24201FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "MediaMemory1",
- .start = 0x24202000,
- .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * VIDEO2 / LX2
- *
- */
- {
- .name = "ST231bImage", /* Delta-Mu 2 image and ram */
- .start = 0x60000000,
- .end = 0x601FFFFF, /* 2MiB */
- .flags = IORESOURCE_IO,
- },
- {
- .name = "ST231bMonitor", /* 8KiB block ST231b monitor */
- .start = 0x60200000,
- .end = 0x60201FFF,
- .flags = IORESOURCE_IO,
- },
- {
- .name = "MediaMemory2",
- .start = 0x60202000,
- .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * Sysaudio Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * DSP_Image_Buff - DSP code and data images (1MB)
- * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
- * ADSC_AUX_Buff - ADSC AUX buffer (16KB)
- * ADSC_Main_Buff - ADSC Main buffer (16KB)
- *
- */
- {
- .name = "DSP_Image_Buff",
- .start = 0x00000000,
- .end = 0x000FFFFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_CPU_PCM_Buff",
- .start = 0x00000000,
- .end = 0x00009FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_AUX_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_Main_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * STAVEM driver/STAPI
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- *
- */
- {
- .name = "AVMEMPartition0",
- .start = 0x63580000,
- .end = 0x64180000 - 1, /* 12 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * DOCSIS Subsystem
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "Docsis",
- .start = 0x62000000,
- .end = 0x62700000 - 1, /* 7 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * GHW HAL Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * GraphicsHeap - PowerTV Graphics Heap
- *
- */
- {
- .name = "GraphicsHeap",
- .start = 0x62700000,
- .end = 0x63500000 - 1, /* 14 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * multi com buffer area
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "MulticomSHM",
- .start = 0x26000000,
- .end = 0x26020000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * DMA Ring buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "BMM_Buffer",
- .start = 0x00000000,
- .end = 0x00280000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer for unit0
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit0
- *
- */
- {
- .name = "DisplayBins0",
- .start = 0x00000000,
- .end = 0x00000FFF, /* 4 KB total */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit1
- *
- */
- {
- .name = "DisplayBins1",
- .start = 0x64AD4000,
- .end = 0x64AD5000 - 1, /* 4 KB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * ITFS
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "ITFS",
- .start = 0x64180000,
- /* 815,104 bytes each for 2 ITFS partitions. */
- .end = 0x6430DFFF,
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * AVFS
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "AvfsDmaMem",
- .start = 0x6430E000,
- /* (945K * 8) = (128K *3) 5 playbacks / 3 server */
- .end = 0x64AD0000 - 1,
- .flags = IORESOURCE_IO,
- },
- {
- .name = "AvfsFileSys",
- .start = 0x64AD0000,
- .end = 0x64AD1000 - 1, /* 4K */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * Smartcard
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Read and write buffers for Internal/External cards
- *
- */
- {
- .name = "SmartCardInfo",
- .start = 0x64AD1000,
- .end = 0x64AD3800 - 1,
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * KAVNET
- * NP Reset Vector - must be of the form xxCxxxxx
- * NP Image - must be video bank 1
- * NP IPC - must be video bank 2
- */
- {
- .name = "NP_Reset_Vector",
- .start = 0x27c00000,
- .end = 0x27c01000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_Image",
- .start = 0x27020000,
- .end = 0x27060000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_IPC",
- .start = 0x63500000,
- .end = 0x63580000 - 1,
- .flags = IORESOURCE_IO,
- },
- /*
- * Add other resources here
- */
- { },
-};
-
-/*
- * NON_DVR_CAPABLE GAIA RESOURCES
- */
-struct resource non_dvr_gaia_resources[] __initdata = {
- /*
- *
- * VIDEO1 / LX1
- *
- */
- {
- .name = "ST231aImage", /* Delta-Mu 1 image and ram */
- .start = 0x24000000,
- .end = 0x241FFFFF, /* 2MiB */
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ST231aMonitor", /* 8KiB block ST231a monitor */
- .start = 0x24200000,
- .end = 0x24201FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "MediaMemory1",
- .start = 0x24202000,
- .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * VIDEO2 / LX2
- *
- */
- {
- .name = "ST231bImage", /* Delta-Mu 2 image and ram */
- .start = 0x60000000,
- .end = 0x601FFFFF, /* 2MiB */
- .flags = IORESOURCE_IO,
- },
- {
- .name = "ST231bMonitor", /* 8KiB block ST231b monitor */
- .start = 0x60200000,
- .end = 0x60201FFF,
- .flags = IORESOURCE_IO,
- },
- {
- .name = "MediaMemory2",
- .start = 0x60202000,
- .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * Sysaudio Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * DSP_Image_Buff - DSP code and data images (1MB)
- * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
- * ADSC_AUX_Buff - ADSC AUX buffer (16KB)
- * ADSC_Main_Buff - ADSC Main buffer (16KB)
- *
- */
- {
- .name = "DSP_Image_Buff",
- .start = 0x00000000,
- .end = 0x000FFFFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_CPU_PCM_Buff",
- .start = 0x00000000,
- .end = 0x00009FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_AUX_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_Main_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * STAVEM driver/STAPI
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- *
- */
- {
- .name = "AVMEMPartition0",
- .start = 0x63580000,
- .end = 0x64180000 - 1, /* 12 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * DOCSIS Subsystem
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "Docsis",
- .start = 0x62000000,
- .end = 0x62700000 - 1, /* 7 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * GHW HAL Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * GraphicsHeap - PowerTV Graphics Heap
- *
- */
- {
- .name = "GraphicsHeap",
- .start = 0x62700000,
- .end = 0x63500000 - 1, /* 14 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * multi com buffer area
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "MulticomSHM",
- .start = 0x26000000,
- .end = 0x26020000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * DMA Ring buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "BMM_Buffer",
- .start = 0x00000000,
- .end = 0x000AA000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer for unit0
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit0
- *
- */
- {
- .name = "DisplayBins0",
- .start = 0x00000000,
- .end = 0x00000FFF, /* 4 KB total */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit1
- *
- */
- {
- .name = "DisplayBins1",
- .start = 0x64AD4000,
- .end = 0x64AD5000 - 1, /* 4 KB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * AVFS: player HAL memory
- *
- *
- */
- {
- .name = "AvfsDmaMem",
- .start = 0x6430E000,
- .end = 0x645D2C00 - 1, /* 945K * 3 for playback */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * PMEM
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Persistent memory for diagnostics.
- *
- */
- {
- .name = "DiagPersistentMemory",
- .start = 0x00000000,
- .end = 0x10000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Smartcard
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Read and write buffers for Internal/External cards
- *
- */
- {
- .name = "SmartCardInfo",
- .start = 0x64AD1000,
- .end = 0x64AD3800 - 1,
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * KAVNET
- * NP Reset Vector - must be of the form xxCxxxxx
- * NP Image - must be video bank 1
- * NP IPC - must be video bank 2
- */
- {
- .name = "NP_Reset_Vector",
- .start = 0x27c00000,
- .end = 0x27c01000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_Image",
- .start = 0x27020000,
- .end = 0x27060000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_IPC",
- .start = 0x63500000,
- .end = 0x63580000 - 1,
- .flags = IORESOURCE_IO,
- },
- { },
-};
diff --git a/arch/mips/powertv/asic/prealloc-zeus.c b/arch/mips/powertv/asic/prealloc-zeus.c
deleted file mode 100644
index 6e76f09c68d..00000000000
--- a/arch/mips/powertv/asic/prealloc-zeus.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Memory pre-allocations for Zeus boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * DVR_CAPABLE RESOURCES
- */
-struct resource dvr_zeus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x20000000, 0x20200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x20200000, 0x20202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x20202000, 0x22000000-1,
- IORESOURCE_MEM)
-
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 2 image (2MiB) */
- PREALLOC_NORMAL("ST231bImage", 0x30000000, 0x30200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 monitor (8KiB) */
- PREALLOC_NORMAL("ST231bMonitor", 0x30200000, 0x30202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory2", 0x30202000, 0x32000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 12MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x40100000, 0x40800000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x46900000, 0x47700000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x47900000, 0x47920000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer
- */
- /* 2.5MiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x00280000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * ITFS
- */
- /* 815,104 bytes each for 2 ITFS partitions. */
- PREALLOC_NORMAL("ITFS", 0x00000000, 0x0018E000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS
- */
- /* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x007c2000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* 4KiB */
- PREALLOC_NORMAL("AvfsFileSys", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-/*
- * NON_DVR_CAPABLE ZEUS RESOURCES
- */
-struct resource non_dvr_zeus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x20000000, 0x20200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x20200000, 0x20202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x20202000, 0x22000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 6MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x40100000, 0x40800000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x46900000, 0x47700000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x47900000, 0x47920000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer
- */
- /* 2.5MiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x00280000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc.h b/arch/mips/powertv/asic/prealloc.h
deleted file mode 100644
index 8e682df1785..00000000000
--- a/arch/mips/powertv/asic/prealloc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Definitions for memory preallocations
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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 _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-#define _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-
-#define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */
-#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
-
-/* "struct resource" array element definition */
-#define PREALLOC(NAME, START, END, FLAGS) { \
- .name = (NAME), \
- .start = (START), \
- .end = (END), \
- .flags = (FLAGS) \
- },
-
-/* Individual resources in the preallocated resource arrays are defined using
- * macros. These macros are conditionally defined based on their
- * corresponding kernel configuration flag:
- * - CONFIG_PREALLOC_NORMAL: preallocate resources for a normal settop box
- * - CONFIG_PREALLOC_TFTP: preallocate the TFTP download resource
- * - CONFIG_PREALLOC_DOCSIS: preallocate the DOCSIS resource
- * - CONFIG_PREALLOC_PMEM: reserve space for persistent memory
- */
-#ifdef CONFIG_PREALLOC_NORMAL
-#define PREALLOC_NORMAL(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_NORMAL(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_TFTP
-#define PREALLOC_TFTP(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_TFTP(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_DOCSIS
-#define PREALLOC_DOCSIS(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_DOCSIS(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_PMEM
-#define PREALLOC_PMEM(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_PMEM(name, start, end, flags)
-#endif
-#endif
diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c
deleted file mode 100644
index 498926377e5..00000000000
--- a/arch/mips/powertv/init.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.
- * All rights reserved.
- * Authors: Carsten Langgaard <carstenl@mips.com>
- * Maciej W. Rozycki <macro@mips.com>
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * PROM library initialisation code.
- */
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-#include <linux/io.h>
-#include <asm/cacheflush.h>
-#include <asm/traps.h>
-
-#include <asm/mips-boards/generic.h>
-#include <asm/mach-powertv/asic.h>
-
-#include "init.h"
-
-static int *_prom_envp;
-unsigned long _prom_memsize;
-
-/*
- * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
- * This macro take care of sign extension, if running in 64-bit mode.
- */
-#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
-
-char *prom_getenv(char *envname)
-{
- char *result = NULL;
-
- if (_prom_envp != NULL) {
- /*
- * Return a pointer to the given environment variable.
- * In 64-bit mode: we're using 64-bit pointers, but all pointers
- * in the PROM structures are only 32-bit, so we need some
- * workarounds, if we are running in 64-bit mode.
- */
- int i, index = 0;
-
- i = strlen(envname);
-
- while (prom_envp(index)) {
- if (strncmp(envname, prom_envp(index), i) == 0) {
- result = prom_envp(index + 1);
- break;
- }
- index += 2;
- }
- }
-
- return result;
-}
-
-void __init prom_init(void)
-{
- int prom_argc;
- char *prom_argv;
-
- prom_argc = fw_arg0;
- prom_argv = (char *) fw_arg1;
- _prom_envp = (int *) fw_arg2;
- _prom_memsize = (unsigned long) fw_arg3;
-
- if (prom_argc == 1) {
- strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
- strlcat(arcs_cmdline, prom_argv, COMMAND_LINE_SIZE);
- }
-
- configure_platform();
- prom_meminit();
-}
diff --git a/arch/mips/powertv/init.h b/arch/mips/powertv/init.h
deleted file mode 100644
index c1a8bd0dbe4..00000000000
--- a/arch/mips/powertv/init.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Definitions from powertv init.c file
- *
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_INIT_H
-#define _POWERTV_INIT_H
-extern unsigned long _prom_memsize;
-extern void prom_meminit(void);
-extern char *prom_getenv(char *name);
-#endif
diff --git a/arch/mips/powertv/ioremap.c b/arch/mips/powertv/ioremap.c
deleted file mode 100644
index d060478aab0..00000000000
--- a/arch/mips/powertv/ioremap.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * ioremap.c
- *
- * Support for mapping between dma_addr_t values a phys_addr_t values.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, 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.
- *
- * 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
- *
- * Author: David VomLehn <dvomlehn@cisco.com>
- *
- * Description: Defines the platform resources for the SA settop.
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/mach-powertv/ioremap.h>
-
-/*
- * Define the sizes of and masks for grains in physical and DMA space. The
- * values are the same but the types are not.
- */
-#define IOR_PHYS_GRAIN ((phys_addr_t) 1 << IOR_LSBITS)
-#define IOR_PHYS_GRAIN_MASK (IOR_PHYS_GRAIN - 1)
-
-#define IOR_DMA_GRAIN ((dma_addr_t) 1 << IOR_LSBITS)
-#define IOR_DMA_GRAIN_MASK (IOR_DMA_GRAIN - 1)
-
-/*
- * Values that, when accessed by an index derived from a phys_addr_t and
- * added to phys_addr_t value, yield a DMA address
- */
-struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
-EXPORT_SYMBOL(_ior_phys_to_dma);
-
-/*
- * Values that, when accessed by an index derived from a dma_addr_t and
- * added to that dma_addr_t value, yield a physical address
- */
-struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];
-EXPORT_SYMBOL(_ior_dma_to_phys);
-
-/**
- * setup_dma_to_phys - set up conversion from DMA to physical addresses
- * @dma_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index
- * into the array _dma_to_phys.
- * @delta: Value that, when added to the DMA address, will yield the
- * physical address
- * @s: Number of bytes in the section of memory with the given delta
- * between DMA and physical addresses.
- */
-static void setup_dma_to_phys(dma_addr_t dma, phys_addr_t delta, dma_addr_t s)
-{
- int dma_idx, first_idx, last_idx;
- phys_addr_t first, last;
-
- /*
- * Calculate the first and last indices, rounding the first up and
- * the second down.
- */
- first = dma & ~IOR_DMA_GRAIN_MASK;
- last = (dma + s - 1) & ~IOR_DMA_GRAIN_MASK;
- first_idx = first >> IOR_LSBITS; /* Convert to indices */
- last_idx = last >> IOR_LSBITS;
-
- for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++)
- _ior_dma_to_phys[dma_idx].offset = delta >> IOR_DMA_SHIFT;
-}
-
-/**
- * setup_phys_to_dma - set up conversion from DMA to physical addresses
- * @phys_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index
- * into the array _phys_to_dma.
- * @delta: Value that, when added to the DMA address, will yield the
- * physical address
- * @s: Number of bytes in the section of memory with the given delta
- * between DMA and physical addresses.
- */
-static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s)
-{
- int phys_idx, first_idx, last_idx;
- phys_addr_t first, last;
-
- /*
- * Calculate the first and last indices, rounding the first up and
- * the second down.
- */
- first = phys & ~IOR_PHYS_GRAIN_MASK;
- last = (phys + s - 1) & ~IOR_PHYS_GRAIN_MASK;
- first_idx = first >> IOR_LSBITS; /* Convert to indices */
- last_idx = last >> IOR_LSBITS;
-
- for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++)
- _ior_phys_to_dma[phys_idx].offset = delta >> IOR_PHYS_SHIFT;
-}
-
-/**
- * ioremap_add_map - add to the physical and DMA address conversion arrays
- * @phys: Process's view of the address of the start of the memory chunk
- * @dma: DMA address of the start of the memory chunk
- * @size: Size, in bytes, of the chunk of memory
- *
- * NOTE: It might be obvious, but the assumption is that all @size bytes have
- * the same offset between the physical address and the DMA address.
- */
-void ioremap_add_map(phys_addr_t phys, phys_addr_t dma, phys_addr_t size)
-{
- if (size == 0)
- return;
-
- if ((dma & IOR_DMA_GRAIN_MASK) != 0 ||
- (phys & IOR_PHYS_GRAIN_MASK) != 0 ||
- (size & IOR_PHYS_GRAIN_MASK) != 0)
- pr_crit("Memory allocation must be in chunks of 0x%x bytes\n",
- IOR_PHYS_GRAIN);
-
- setup_dma_to_phys(dma, phys - dma, size);
- setup_phys_to_dma(phys, dma - phys, size);
-}
diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c
deleted file mode 100644
index bc2f3ca22b4..00000000000
--- a/arch/mips/powertv/memory.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Apparently originally from arch/mips/malta-memory.c. Modified to work
- * with the PowerTV bootloader.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/pfn.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/sections.h>
-
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/ioremap.h>
-
-#include "init.h"
-
-/* Memory constants */
-#define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */
-#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
-#define DEFAULT_MEMSIZE MEBIBYTE(128) /* If no memsize provided */
-
-#define BLDR_SIZE KIBIBYTE(256) /* Memory reserved for bldr */
-#define RV_SIZE MEBIBYTE(4) /* Size of reset vector */
-
-#define LOW_MEM_END 0x20000000 /* Highest low memory address */
-#define BLDR_ALIAS 0x10000000 /* Bootloader address */
-#define RV_PHYS 0x1fc00000 /* Reset vector address */
-#define LOW_RAM_END RV_PHYS /* End of real RAM in low mem */
-
-/*
- * Very low-level conversion from processor physical address to device
- * DMA address for the first bank of memory.
- */
-#define PHYS_TO_DMA(paddr) ((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS))
-
-unsigned long ptv_memsize;
-
-/*
- * struct low_mem_reserved - Items in low memory that are reserved
- * @start: Physical address of item
- * @size: Size, in bytes, of this item
- * @is_aliased: True if this is RAM aliased from another location. If false,
- * it is something other than aliased RAM and the RAM in the
- * unaliased address is still visible outside of low memory.
- */
-struct low_mem_reserved {
- phys_addr_t start;
- phys_addr_t size;
- bool is_aliased;
-};
-
-/*
- * Must be in ascending address order
- */
-struct low_mem_reserved low_mem_reserved[] = {
- {BLDR_ALIAS, BLDR_SIZE, true}, /* Bootloader RAM */
- {RV_PHYS, RV_SIZE, false}, /* Reset vector */
-};
-
-/*
- * struct mem_layout - layout of a piece of the system RAM
- * @phys: Physical address of the start of this piece of RAM. This is the
- * address at which both the processor and I/O devices see the
- * RAM.
- * @alias: Alias of this piece of memory in order to make it appear in
- * the low memory part of the processor's address space. I/O
- * devices don't see anything here.
- * @size: Size, in bytes, of this piece of RAM
- */
-struct mem_layout {
- phys_addr_t phys;
- phys_addr_t alias;
- phys_addr_t size;
-};
-
-/*
- * struct mem_layout_list - list descriptor for layouts of system RAM pieces
- * @family: Specifies the family being described
- * @n: Number of &struct mem_layout elements
- * @layout: Pointer to the list of &mem_layout structures
- */
-struct mem_layout_list {
- enum family_type family;
- size_t n;
- struct mem_layout *layout;
-};
-
-static struct mem_layout f1500_layout[] = {
- {0x20000000, 0x10000000, MEBIBYTE(256)},
-};
-
-static struct mem_layout f4500_layout[] = {
- {0x40000000, 0x10000000, MEBIBYTE(256)},
- {0x20000000, 0x20000000, MEBIBYTE(32)},
-};
-
-static struct mem_layout f8500_layout[] = {
- {0x40000000, 0x10000000, MEBIBYTE(256)},
- {0x20000000, 0x20000000, MEBIBYTE(32)},
- {0x30000000, 0x30000000, MEBIBYTE(32)},
-};
-
-static struct mem_layout fx600_layout[] = {
- {0x20000000, 0x10000000, MEBIBYTE(256)},
- {0x60000000, 0x60000000, MEBIBYTE(128)},
-};
-
-static struct mem_layout_list layout_list[] = {
- {FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout},
- {FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout},
- {FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout},
- {FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout},
- {FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout},
- {FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout},
- {FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout},
- {FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout},
- {FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout},
- {FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout},
-};
-
-/* If we can't determine the layout, use this */
-static struct mem_layout default_layout[] = {
- {0x20000000, 0x10000000, MEBIBYTE(128)},
-};
-
-/**
- * register_non_ram - register low memory not available for RAM usage
- */
-static __init void register_non_ram(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++)
- add_memory_region(low_mem_reserved[i].start,
- low_mem_reserved[i].size, BOOT_MEM_RESERVED);
-}
-
-/**
- * get_memsize - get the size of memory as a single bank
- */
-static phys_addr_t get_memsize(void)
-{
- static char cmdline[COMMAND_LINE_SIZE] __initdata;
- phys_addr_t memsize = 0;
- char *memsize_str;
- char *ptr;
-
- /* Check the command line first for a memsize directive */
- strcpy(cmdline, arcs_cmdline);
- ptr = strstr(cmdline, "memsize=");
- if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
- ptr = strstr(ptr, " memsize=");
-
- if (ptr) {
- memsize = memparse(ptr + 8, &ptr);
- } else {
- /* otherwise look in the environment */
- memsize_str = prom_getenv("memsize");
-
- if (memsize_str != NULL) {
- pr_info("prom memsize = %s\n", memsize_str);
- memsize = simple_strtol(memsize_str, NULL, 0);
- }
-
- if (memsize == 0) {
- if (_prom_memsize != 0) {
- memsize = _prom_memsize;
- pr_info("_prom_memsize = 0x%x\n", memsize);
- /* add in memory that the bootloader doesn't
- * report */
- memsize += BLDR_SIZE;
- } else {
- memsize = DEFAULT_MEMSIZE;
- pr_info("Memsize not passed by bootloader, "
- "defaulting to 0x%x\n", memsize);
- }
- }
- }
-
- return memsize;
-}
-
-/**
- * register_low_ram - register an aliased section of RAM
- * @p: Alias address of memory
- * @n: Number of bytes in this section of memory
- *
- * Returns the number of bytes registered
- *
- */
-static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n)
-{
- phys_addr_t s;
- int i;
- phys_addr_t orig_n;
-
- orig_n = n;
-
- BUG_ON(p + n > RV_PHYS);
-
- for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) {
- phys_addr_t start;
- phys_addr_t size;
-
- start = low_mem_reserved[i].start;
- size = low_mem_reserved[i].size;
-
- /* Handle memory before this low memory section */
- if (p < start) {
- phys_addr_t s;
- s = min(n, start - p);
- add_memory_region(p, s, BOOT_MEM_RAM);
- p += s;
- n -= s;
- }
-
- /* Handle the low memory section itself. If it's aliased,
- * we reduce the number of byes left, but if not, the RAM
- * is available elsewhere and we don't reduce the number of
- * bytes remaining. */
- if (p == start) {
- if (low_mem_reserved[i].is_aliased) {
- s = min(n, size);
- n -= s;
- p += s;
- } else
- p += n;
- }
- }
-
- return orig_n - n;
-}
-
-/*
- * register_ram - register real RAM
- * @p: Address of memory as seen by devices
- * @alias: If the memory is seen at an additional address by the processor,
- * this will be the address, otherwise it is the same as @p.
- * @n: Number of bytes in this section of memory
- */
-static __init void register_ram(phys_addr_t p, phys_addr_t alias,
- phys_addr_t n)
-{
- /*
- * If some or all of this memory has an alias, break it into the
- * aliased and non-aliased portion.
- */
- if (p != alias) {
- phys_addr_t alias_size;
- phys_addr_t registered;
-
- alias_size = min(n, LOW_RAM_END - alias);
- registered = register_low_ram(alias, alias_size);
- ioremap_add_map(alias, p, n);
- n -= registered;
- p += registered;
- }
-
-#ifdef CONFIG_HIGHMEM
- if (n != 0) {
- add_memory_region(p, n, BOOT_MEM_RAM);
- ioremap_add_map(p, p, n);
- }
-#endif
-}
-
-/**
- * register_address_space - register things in the address space
- * @memsize: Number of bytes of RAM installed
- *
- * Takes the given number of bytes of RAM and registers as many of the regions,
- * or partial regions, as it can. So, the default configuration might have
- * two regions with 256 MiB each. If the memsize passed in on the command line
- * is 384 MiB, it will register the first region with 256 MiB and the second
- * with 128 MiB.
- */
-static __init void register_address_space(phys_addr_t memsize)
-{
- int i;
- phys_addr_t size;
- size_t n;
- struct mem_layout *layout;
- enum family_type family;
-
- /*
- * Register all of the things that aren't available to the kernel as
- * memory.
- */
- register_non_ram();
-
- /* Find the appropriate memory description */
- family = platform_get_family();
-
- for (i = 0; i < ARRAY_SIZE(layout_list); i++) {
- if (layout_list[i].family == family)
- break;
- }
-
- if (i == ARRAY_SIZE(layout_list)) {
- n = ARRAY_SIZE(default_layout);
- layout = default_layout;
- } else {
- n = layout_list[i].n;
- layout = layout_list[i].layout;
- }
-
- for (i = 0; memsize != 0 && i < n; i++) {
- size = min(memsize, layout[i].size);
- register_ram(layout[i].phys, layout[i].alias, size);
- memsize -= size;
- }
-}
-
-void __init prom_meminit(void)
-{
- ptv_memsize = get_memsize();
- register_address_space(ptv_memsize);
-}
-
-void __init prom_free_prom_memory(void)
-{
- unsigned long addr;
- int i;
-
- for (i = 0; i < boot_mem_map.nr_map; i++) {
- if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
- continue;
-
- addr = boot_mem_map.map[i].addr;
- free_init_pages("prom memory",
- addr, addr + boot_mem_map.map[i].size);
- }
-}
diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile
deleted file mode 100644
index 2610a6af5b2..00000000000
--- a/arch/mips/powertv/pci/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2009 Scientific-Atlanta, 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.
-#
-# 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
-#
-
-obj-$(CONFIG_PCI) += fixup-powertv.o
diff --git a/arch/mips/powertv/pci/fixup-powertv.c b/arch/mips/powertv/pci/fixup-powertv.c
deleted file mode 100644
index d7ecbae64a6..00000000000
--- a/arch/mips/powertv/pci/fixup-powertv.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/pci.h>
-#include <asm/mach-powertv/interrupts.h>
-#include "powertv-pci.h"
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- return asic_pcie_map_irq(dev, slot, pin);
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
-
-/*
- * asic_pcie_map_irq
- *
- * Parameters:
- * *dev - pointer to a pci_dev structure (not used)
- * slot - slot number (not used)
- * pin - pin number (not used)
- *
- * Return Value:
- * Returns: IRQ number (always the PCI Express IRQ number)
- *
- * Description:
- * asic_pcie_map_irq will return the IRQ number of the PCI Express interrupt.
- *
- */
-int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- return irq_pciexp;
-}
-EXPORT_SYMBOL(asic_pcie_map_irq);
diff --git a/arch/mips/powertv/pci/powertv-pci.h b/arch/mips/powertv/pci/powertv-pci.h
deleted file mode 100644
index 1b5886bbd75..00000000000
--- a/arch/mips/powertv/pci/powertv-pci.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * powertv-pci.c
- *
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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
- */
-/*
- * Local definitions for the powertv PCI code
- */
-
-#ifndef _POWERTV_PCI_POWERTV_PCI_H_
-#define _POWERTV_PCI_POWERTV_PCI_H_
-extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-extern int asic_pcie_init(void);
-extern int asic_pcie_init(void);
-
-extern int log_level;
-#endif
diff --git a/arch/mips/powertv/powertv-clock.h b/arch/mips/powertv/powertv-clock.h
deleted file mode 100644
index d94c5431148..00000000000
--- a/arch/mips/powertv/powertv-clock.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_POWERTV_CLOCK_H
-#define _POWERTV_POWERTV_CLOCK_H
-extern int powertv_clockevent_init(void);
-extern void powertv_clocksource_init(void);
-extern unsigned int mips_get_pll_freq(void);
-#endif
diff --git a/arch/mips/powertv/powertv-usb.c b/arch/mips/powertv/powertv-usb.c
deleted file mode 100644
index d845eace58e..00000000000
--- a/arch/mips/powertv/powertv-usb.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * powertv-usb.c
- *
- * Description: ASIC-specific USB device setup and shutdown
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/interrupts.h>
-
-/* misc_clk_ctl1 values */
-#define MCC1_30MHZ_POWERUP_SELECT (1 << 14)
-#define MCC1_DIV9 (1 << 13)
-#define MCC1_ETHMIPS_POWERUP_SELECT (1 << 11)
-#define MCC1_USB_POWERUP_SELECT (1 << 1)
-#define MCC1_CLOCK108_POWERUP_SELECT (1 << 0)
-
-/* Possible values for clock select */
-#define MCC1_USB_CLOCK_HIGH_Z (0 << 4)
-#define MCC1_USB_CLOCK_48MHZ (1 << 4)
-#define MCC1_USB_CLOCK_24MHZ (2 << 4)
-#define MCC1_USB_CLOCK_6MHZ (3 << 4)
-
-#define MCC1_CONFIG (MCC1_30MHZ_POWERUP_SELECT | \
- MCC1_DIV9 | \
- MCC1_ETHMIPS_POWERUP_SELECT | \
- MCC1_USB_POWERUP_SELECT | \
- MCC1_CLOCK108_POWERUP_SELECT)
-
-/* misc_clk_ctl2 values */
-#define MCC2_GMII_GCLK_TO_PAD (1 << 31)
-#define MCC2_ETHER125_0_CLOCK_SELECT (1 << 29)
-#define MCC2_RMII_0_CLOCK_SELECT (1 << 28)
-#define MCC2_GMII_TX0_CLOCK_SELECT (1 << 27)
-#define MCC2_GMII_RX0_CLOCK_SELECT (1 << 26)
-#define MCC2_ETHER125_1_CLOCK_SELECT (1 << 24)
-#define MCC2_RMII_1_CLOCK_SELECT (1 << 23)
-#define MCC2_GMII_TX1_CLOCK_SELECT (1 << 22)
-#define MCC2_GMII_RX1_CLOCK_SELECT (1 << 21)
-#define MCC2_ETHER125_2_CLOCK_SELECT (1 << 19)
-#define MCC2_RMII_2_CLOCK_SELECT (1 << 18)
-#define MCC2_GMII_TX2_CLOCK_SELECT (1 << 17)
-#define MCC2_GMII_RX2_CLOCK_SELECT (1 << 16)
-
-#define ETHER_CLK_CONFIG (MCC2_GMII_GCLK_TO_PAD | \
- MCC2_ETHER125_0_CLOCK_SELECT | \
- MCC2_RMII_0_CLOCK_SELECT | \
- MCC2_GMII_TX0_CLOCK_SELECT | \
- MCC2_GMII_RX0_CLOCK_SELECT | \
- MCC2_ETHER125_1_CLOCK_SELECT | \
- MCC2_RMII_1_CLOCK_SELECT | \
- MCC2_GMII_TX1_CLOCK_SELECT | \
- MCC2_GMII_RX1_CLOCK_SELECT | \
- MCC2_ETHER125_2_CLOCK_SELECT | \
- MCC2_RMII_2_CLOCK_SELECT | \
- MCC2_GMII_TX2_CLOCK_SELECT | \
- MCC2_GMII_RX2_CLOCK_SELECT)
-
-/* misc_clk_ctl2 definitions for Gaia */
-#define FSX4A_REF_SELECT (1 << 16)
-#define FSX4B_REF_SELECT (1 << 17)
-#define FSX4C_REF_SELECT (1 << 18)
-#define DDR_PLL_REF_SELECT (1 << 19)
-#define MIPS_PLL_REF_SELECT (1 << 20)
-
-/* Definitions for the QAM frequency select register FS432X4A4_QAM_CTL */
-#define QAM_FS_SDIV_SHIFT 29
-#define QAM_FS_MD_SHIFT 24
-#define QAM_FS_MD_MASK 0x1f /* Cut down to 5 bits */
-#define QAM_FS_PE_SHIFT 8
-
-#define QAM_FS_DISABLE_DIVIDE_BY_3 (1 << 5)
-#define QAM_FS_ENABLE_PROGRAM (1 << 4)
-#define QAM_FS_ENABLE_OUTPUT (1 << 3)
-#define QAM_FS_SELECT_TEST_BYPASS (1 << 2)
-#define QAM_FS_DISABLE_DIGITAL_STANDBY (1 << 1)
-#define QAM_FS_CHOOSE_FS (1 << 0)
-
-/* Definitions for fs432x4a_ctl register */
-#define QAM_FS_NSDIV_54MHZ (1 << 2)
-
-/* Definitions for bcm1_usb2_ctl register */
-#define BCM1_USB2_CTL_BISTOK (1 << 11)
-#define BCM1_USB2_CTL_PORT2_SHIFT_JK (1 << 7)
-#define BCM1_USB2_CTL_PORT1_SHIFT_JK (1 << 6)
-#define BCM1_USB2_CTL_PORT2_FAST_EDGE (1 << 5)
-#define BCM1_USB2_CTL_PORT1_FAST_EDGE (1 << 4)
-#define BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH (1 << 1)
-#define BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH (1 << 0)
-
-/* Definitions for crt_spare register */
-#define CRT_SPARE_PORT2_SHIFT_JK (1 << 21)
-#define CRT_SPARE_PORT1_SHIFT_JK (1 << 20)
-#define CRT_SPARE_PORT2_FAST_EDGE (1 << 19)
-#define CRT_SPARE_PORT1_FAST_EDGE (1 << 18)
-#define CRT_SPARE_DIVIDE_BY_9_FROM_432 (1 << 17)
-#define CRT_SPARE_USB_DIVIDE_BY_9 (1 << 16)
-
-/* Definitions for usb2_stbus_obc register */
-#define USB_STBUS_OBC_STORE32_LOAD32 0x3
-
-/* Definitions for usb2_stbus_mess_size register */
-#define USB2_STBUS_MESS_SIZE_2 0x1 /* 2 packets */
-
-/* Definitions for usb2_stbus_chunk_size register */
-#define USB2_STBUS_CHUNK_SIZE_2 0x1 /* 2 packets */
-
-/* Definitions for usb2_strap register */
-#define USB2_STRAP_HFREQ_SELECT 0x1
-
-/*
- * USB Host Resource Definition
- */
-
-static struct resource ehci_resources[] = {
- {
- .parent = &asic_resource,
- .start = 0,
- .end = 0xff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = irq_usbehci,
- .end = irq_usbehci,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static u64 ehci_dmamask = 0xffffffffULL;
-
-static struct platform_device ehci_device = {
- .name = "powertv-ehci",
- .id = 0,
- .num_resources = 2,
- .resource = ehci_resources,
- .dev = {
- .dma_mask = &ehci_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
-};
-
-static struct resource ohci_resources[] = {
- {
- .parent = &asic_resource,
- .start = 0,
- .end = 0xff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = irq_usbohci,
- .end = irq_usbohci,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static u64 ohci_dmamask = 0xffffffffULL;
-
-static struct platform_device ohci_device = {
- .name = "powertv-ohci",
- .id = 0,
- .num_resources = 2,
- .resource = ohci_resources,
- .dev = {
- .dma_mask = &ohci_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
-};
-
-static unsigned usb_users;
-static DEFINE_SPINLOCK(usb_regs_lock);
-
-/*
- *
- * fs_update - set frequency synthesizer for USB
- * @pe_bits Phase tap setting
- * @md_bits Coarse selector bus for algorithm of phase tap
- * @sdiv_bits Output divider setting
- * @disable_div_by_3 Either QAM_FS_DISABLE_DIVIDE_BY_3 or zero
- * @standby Either QAM_FS_DISABLE_DIGITAL_STANDBY or zero
- *
- * QAM frequency selection code, which affects the frequency at which USB
- * runs. The frequency is calculated as:
- * 2^15 * ndiv * Fin
- * Fout = ------------------------------------------------------------
- * (sdiv * (ipe * (1 + md/32) - (ipe - 2^15)*(1 + (md + 1)/32)))
- * where:
- * Fin 54 MHz
- * ndiv QAM_FS_NSDIV_54MHZ ? 8 : 16
- * sdiv 1 << (sdiv_bits + 1)
- * ipe Same as pe_bits
- * md A five-bit, two's-complement integer (range [-16, 15]), which
- * is the lower 5 bits of md_bits.
- */
-static void fs_update(u32 pe_bits, int md_bits, u32 sdiv_bits,
- u32 disable_div_by_3, u32 standby)
-{
- u32 val;
-
- val = ((sdiv_bits << QAM_FS_SDIV_SHIFT) |
- ((md_bits & QAM_FS_MD_MASK) << QAM_FS_MD_SHIFT) |
- (pe_bits << QAM_FS_PE_SHIFT) |
- QAM_FS_ENABLE_OUTPUT |
- standby |
- disable_div_by_3);
- asic_write(val, fs432x4b4_usb_ctl);
- asic_write(val | QAM_FS_ENABLE_PROGRAM, fs432x4b4_usb_ctl);
- asic_write(val | QAM_FS_ENABLE_PROGRAM | QAM_FS_CHOOSE_FS,
- fs432x4b4_usb_ctl);
-}
-
-/*
- * usb_eye_configure - for optimizing the shape USB eye waveform
- * @set: Bits to set in the register
- * @clear: Bits to clear in the register; each bit with a one will
- * be set in the register, zero bits will not be modified
- */
-static void usb_eye_configure(u32 set, u32 clear)
-{
- u32 old;
-
- old = asic_read(crt_spare);
- old |= set;
- old &= ~clear;
- asic_write(old, crt_spare);
-}
-
-/*
- * platform_configure_usb - usb configuration based on platform type.
- */
-static void platform_configure_usb(void)
-{
- u32 bcm1_usb2_ctl_value;
- enum asic_type asic_type;
- unsigned long flags;
-
- spin_lock_irqsave(&usb_regs_lock, flags);
- usb_users++;
-
- if (usb_users != 1) {
- spin_unlock_irqrestore(&usb_regs_lock, flags);
- return;
- }
-
- asic_type = platform_get_asic();
-
- switch (asic_type) {
- case ASIC_ZEUS:
- fs_update(0x0000, -15, 0x02, 0, 0);
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- case ASIC_CRONUS:
- case ASIC_CRONUSLITE:
- usb_eye_configure(0, CRT_SPARE_USB_DIVIDE_BY_9);
- fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3,
- QAM_FS_DISABLE_DIGITAL_STANDBY);
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- case ASIC_CALLIOPE:
- fs_update(0x0000, -15, 0x02, QAM_FS_DISABLE_DIVIDE_BY_3,
- QAM_FS_DISABLE_DIGITAL_STANDBY);
-
- switch (platform_get_family()) {
- case FAMILY_1500VZE:
- break;
-
- case FAMILY_1500VZF:
- usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK |
- CRT_SPARE_PORT1_SHIFT_JK |
- CRT_SPARE_PORT2_FAST_EDGE |
- CRT_SPARE_PORT1_FAST_EDGE, 0);
- break;
-
- default:
- usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK |
- CRT_SPARE_PORT1_SHIFT_JK, 0);
- break;
- }
-
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK |
- BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- case ASIC_GAIA:
- fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3,
- QAM_FS_DISABLE_DIGITAL_STANDBY);
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK |
- BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- default:
- pr_err("Unknown ASIC type: %d\n", asic_type);
- bcm1_usb2_ctl_value = 0;
- break;
- }
-
- /* turn on USB power */
- asic_write(0, usb2_strap);
- /* Enable all OHCI interrupts */
- asic_write(bcm1_usb2_ctl_value, usb2_control);
- /* usb2_stbus_obc store32/load32 */
- asic_write(USB_STBUS_OBC_STORE32_LOAD32, usb2_stbus_obc);
- /* usb2_stbus_mess_size 2 packets */
- asic_write(USB2_STBUS_MESS_SIZE_2, usb2_stbus_mess_size);
- /* usb2_stbus_chunk_size 2 packets */
- asic_write(USB2_STBUS_CHUNK_SIZE_2, usb2_stbus_chunk_size);
- spin_unlock_irqrestore(&usb_regs_lock, flags);
-}
-
-static void platform_unconfigure_usb(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&usb_regs_lock, flags);
- usb_users--;
- if (usb_users == 0)
- asic_write(USB2_STRAP_HFREQ_SELECT, usb2_strap);
- spin_unlock_irqrestore(&usb_regs_lock, flags);
-}
-
-/*
- * Set up the USB EHCI interface
- */
-void platform_configure_usb_ehci()
-{
- platform_configure_usb();
-}
-EXPORT_SYMBOL(platform_configure_usb_ehci);
-
-/*
- * Set up the USB OHCI interface
- */
-void platform_configure_usb_ohci()
-{
- platform_configure_usb();
-}
-EXPORT_SYMBOL(platform_configure_usb_ohci);
-
-/*
- * Shut the USB EHCI interface down
- */
-void platform_unconfigure_usb_ehci()
-{
- platform_unconfigure_usb();
-}
-EXPORT_SYMBOL(platform_unconfigure_usb_ehci);
-
-/*
- * Shut the USB OHCI interface down
- */
-void platform_unconfigure_usb_ohci()
-{
- platform_unconfigure_usb();
-}
-EXPORT_SYMBOL(platform_unconfigure_usb_ohci);
-
-/**
- * platform_devices_init - sets up USB device resourse.
- */
-int __init platform_usb_devices_init(struct platform_device **ehci_dev,
- struct platform_device **ohci_dev)
-{
- *ehci_dev = &ehci_device;
- ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase);
- ehci_resources[0].end += ehci_resources[0].start;
-
- *ohci_dev = &ohci_device;
- ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision);
- ohci_resources[0].end += ohci_resources[0].start;
-
- return 0;
-}
diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c
deleted file mode 100644
index 24689bff103..00000000000
--- a/arch/mips/powertv/powertv_setup.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/screen_info.h>
-#include <linux/notifier.h>
-#include <linux/etherdevice.h>
-#include <linux/if_ether.h>
-#include <linux/ctype.h>
-#include <linux/cpu.h>
-#include <linux/time.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mips-boards/generic.h>
-#include <asm/dma.h>
-#include <asm/asm.h>
-#include <asm/traps.h>
-#include <asm/asm-offsets.h>
-#include "reset.h"
-
-#define VAL(n) STR(n)
-
-/*
- * Macros for loading addresses and storing registers:
- * LONG_L_ Stringified version of LONG_L for use in asm() statement
- * LONG_S_ Stringified version of LONG_S for use in asm() statement
- * PTR_LA_ Stringified version of PTR_LA for use in asm() statement
- * REG_SIZE Number of 8-bit bytes in a full width register
- */
-#define LONG_L_ VAL(LONG_L) " "
-#define LONG_S_ VAL(LONG_S) " "
-#define PTR_LA_ VAL(PTR_LA) " "
-
-#ifdef CONFIG_64BIT
-#warning TODO: 64-bit code needs to be verified
-#define REG_SIZE "8" /* In bytes */
-#endif
-
-#ifdef CONFIG_32BIT
-#define REG_SIZE "4" /* In bytes */
-#endif
-
-static void register_panic_notifier(void);
-static int panic_handler(struct notifier_block *notifier_block,
- unsigned long event, void *cause_string);
-
-const char *get_system_type(void)
-{
- return "PowerTV";
-}
-
-void __init plat_mem_setup(void)
-{
- panic_on_oops = 1;
- register_panic_notifier();
-
-#if 0
- mips_pcibios_init();
-#endif
- mips_reboot_setup();
-}
-
-/*
- * Install a panic notifier for platform-specific diagnostics
- */
-static void register_panic_notifier()
-{
- static struct notifier_block panic_notifier = {
- .notifier_call = panic_handler,
- .next = NULL,
- .priority = INT_MAX
- };
- atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
-}
-
-static int panic_handler(struct notifier_block *notifier_block,
- unsigned long event, void *cause_string)
-{
- struct pt_regs my_regs;
-
- /* Save all of the registers */
- {
- unsigned long at, v0, v1; /* Must be on the stack */
-
- /* Start by saving $at and v0 on the stack. We use $at
- * ourselves, but it looks like the compiler may use v0 or v1
- * to load the address of the pt_regs structure. We'll come
- * back later to store the registers in the pt_regs
- * structure. */
- __asm__ __volatile__ (
- ".set noat\n"
- LONG_S_ "$at, %[at]\n"
- LONG_S_ "$2, %[v0]\n"
- LONG_S_ "$3, %[v1]\n"
- :
- [at] "=m" (at),
- [v0] "=m" (v0),
- [v1] "=m" (v1)
- :
- : "at"
- );
-
- __asm__ __volatile__ (
- ".set noat\n"
- "move $at, %[pt_regs]\n"
-
- /* Argument registers */
- LONG_S_ "$4, " VAL(PT_R4) "($at)\n"
- LONG_S_ "$5, " VAL(PT_R5) "($at)\n"
- LONG_S_ "$6, " VAL(PT_R6) "($at)\n"
- LONG_S_ "$7, " VAL(PT_R7) "($at)\n"
-
- /* Temporary regs */
- LONG_S_ "$8, " VAL(PT_R8) "($at)\n"
- LONG_S_ "$9, " VAL(PT_R9) "($at)\n"
- LONG_S_ "$10, " VAL(PT_R10) "($at)\n"
- LONG_S_ "$11, " VAL(PT_R11) "($at)\n"
- LONG_S_ "$12, " VAL(PT_R12) "($at)\n"
- LONG_S_ "$13, " VAL(PT_R13) "($at)\n"
- LONG_S_ "$14, " VAL(PT_R14) "($at)\n"
- LONG_S_ "$15, " VAL(PT_R15) "($at)\n"
-
- /* "Saved" registers */
- LONG_S_ "$16, " VAL(PT_R16) "($at)\n"
- LONG_S_ "$17, " VAL(PT_R17) "($at)\n"
- LONG_S_ "$18, " VAL(PT_R18) "($at)\n"
- LONG_S_ "$19, " VAL(PT_R19) "($at)\n"
- LONG_S_ "$20, " VAL(PT_R20) "($at)\n"
- LONG_S_ "$21, " VAL(PT_R21) "($at)\n"
- LONG_S_ "$22, " VAL(PT_R22) "($at)\n"
- LONG_S_ "$23, " VAL(PT_R23) "($at)\n"
-
- /* Add'l temp regs */
- LONG_S_ "$24, " VAL(PT_R24) "($at)\n"
- LONG_S_ "$25, " VAL(PT_R25) "($at)\n"
-
- /* Kernel temp regs */
- LONG_S_ "$26, " VAL(PT_R26) "($at)\n"
- LONG_S_ "$27, " VAL(PT_R27) "($at)\n"
-
- /* Global pointer, stack pointer, frame pointer and
- * return address */
- LONG_S_ "$gp, " VAL(PT_R28) "($at)\n"
- LONG_S_ "$sp, " VAL(PT_R29) "($at)\n"
- LONG_S_ "$fp, " VAL(PT_R30) "($at)\n"
- LONG_S_ "$ra, " VAL(PT_R31) "($at)\n"
-
- /* Now we can get the $at and v0 registers back and
- * store them */
- LONG_L_ "$8, %[at]\n"
- LONG_S_ "$8, " VAL(PT_R1) "($at)\n"
- LONG_L_ "$8, %[v0]\n"
- LONG_S_ "$8, " VAL(PT_R2) "($at)\n"
- LONG_L_ "$8, %[v1]\n"
- LONG_S_ "$8, " VAL(PT_R3) "($at)\n"
- :
- :
- [at] "m" (at),
- [v0] "m" (v0),
- [v1] "m" (v1),
- [pt_regs] "r" (&my_regs)
- : "at", "t0"
- );
-
- /* Set the current EPC value to be the current location in this
- * function */
- __asm__ __volatile__ (
- ".set noat\n"
- "1:\n"
- PTR_LA_ "$at, 1b\n"
- LONG_S_ "$at, %[cp0_epc]\n"
- :
- [cp0_epc] "=m" (my_regs.cp0_epc)
- :
- : "at"
- );
-
- my_regs.cp0_cause = read_c0_cause();
- my_regs.cp0_status = read_c0_status();
- }
-
- pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... "
- "zzzz... \n");
-
- return NOTIFY_DONE;
-}
-
-/* Information about the RF MAC address, if one was supplied on the
- * command line. */
-static bool have_rfmac;
-static u8 rfmac[ETH_ALEN];
-
-static int rfmac_param(char *p)
-{
- u8 *q;
- bool is_high_nibble;
- int c;
-
- /* Skip a leading "0x", if present */
- if (*p == '0' && *(p+1) == 'x')
- p += 2;
-
- q = rfmac;
- is_high_nibble = true;
-
- for (c = (unsigned char) *p++;
- isxdigit(c) && q - rfmac < ETH_ALEN;
- c = (unsigned char) *p++) {
- int nibble;
-
- nibble = (isdigit(c) ? (c - '0') :
- (isupper(c) ? c - 'A' + 10 : c - 'a' + 10));
-
- if (is_high_nibble)
- *q = nibble << 4;
- else
- *q++ |= nibble;
-
- is_high_nibble = !is_high_nibble;
- }
-
- /* If we parsed all the way to the end of the parameter value and
- * parsed all ETH_ALEN bytes, we have a usable RF MAC address */
- have_rfmac = (c == '\0' && q - rfmac == ETH_ALEN);
-
- return 0;
-}
-
-early_param("rfmac", rfmac_param);
-
-/*
- * Generate an Ethernet MAC address that has a good chance of being unique.
- * @addr: Pointer to six-byte array containing the Ethernet address
- * Generates an Ethernet MAC address that is highly likely to be unique for
- * this particular system on a network with other systems of the same type.
- *
- * The problem we are solving is that, when eth_random_addr() is used to
- * generate MAC addresses at startup, there isn't much entropy for the random
- * number generator to use and the addresses it produces are fairly likely to
- * be the same as those of other identical systems on the same local network.
- * This is true even for relatively small numbers of systems (for the reason
- * why, see the Wikipedia entry for "Birthday problem" at:
- * http://en.wikipedia.org/wiki/Birthday_problem
- *
- * The good news is that we already have a MAC address known to be unique, the
- * RF MAC address. The bad news is that this address is already in use on the
- * RF interface. Worse, the obvious trick, taking the RF MAC address and
- * turning on the locally managed bit, has already been used for other devices.
- * Still, this does give us something to work with.
- *
- * The approach we take is:
- * 1. If we can't get the RF MAC Address, just call eth_random_addr.
- * 2. Use the 24-bit NIC-specific bits of the RF MAC address as the last 24
- * bits of the new address. This is very likely to be unique, except for
- * the current box.
- * 3. To avoid using addresses already on the current box, we set the top
- * six bits of the address with a value different from any currently
- * registered Scientific Atlanta organizationally unique identifyer
- * (OUI). This avoids duplication with any addresses on the system that
- * were generated from valid Scientific Atlanta-registered address by
- * simply flipping the locally managed bit.
- * 4. We aren't generating a multicast address, so we leave the multicast
- * bit off. Since we aren't using a registered address, we have to set
- * the locally managed bit.
- * 5. We then randomly generate the remaining 16-bits. This does two
- * things:
- * a. It allows us to call this function for more than one device
- * in this system
- * b. It ensures that things will probably still work even if
- * some device on the device network has a locally managed
- * address that matches the top six bits from step 2.
- */
-void platform_random_ether_addr(u8 addr[ETH_ALEN])
-{
- const int num_random_bytes = 2;
- const unsigned char non_sciatl_oui_bits = 0xc0u;
- const unsigned char mac_addr_locally_managed = (1 << 1);
-
- if (!have_rfmac) {
- pr_warning("rfmac not available on command line; "
- "generating random MAC address\n");
- eth_random_addr(addr);
- }
-
- else {
- int i;
-
- /* Set the first byte to something that won't match a Scientific
- * Atlanta OUI, is locally managed, and isn't a multicast
- * address */
- addr[0] = non_sciatl_oui_bits | mac_addr_locally_managed;
-
- /* Get some bytes of random address information */
- get_random_bytes(&addr[1], num_random_bytes);
-
- /* Copy over the NIC-specific bits of the RF MAC address */
- for (i = 1 + num_random_bytes; i < ETH_ALEN; i++)
- addr[i] = rfmac[i];
- }
-}
diff --git a/arch/mips/powertv/reset.c b/arch/mips/powertv/reset.c
deleted file mode 100644
index 11c32fbf278..00000000000
--- a/arch/mips/powertv/reset.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#include <linux/pm.h>
-
-#include <linux/io.h>
-#include <asm/reboot.h> /* Not included by linux/reboot.h */
-
-#include <asm/mach-powertv/asic_regs.h>
-#include "reset.h"
-
-static void mips_machine_restart(char *command)
-{
- writel(0x1, asic_reg_addr(watchdog));
-}
-
-void mips_reboot_setup(void)
-{
- _machine_restart = mips_machine_restart;
-}
diff --git a/arch/mips/powertv/reset.h b/arch/mips/powertv/reset.h
deleted file mode 100644
index 888fd09e262..00000000000
--- a/arch/mips/powertv/reset.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Definitions from powertv reset.c file
- *
- * Copyright (C) 2009 Cisco Systems, 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.
- *
- * 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
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_POWERTV_RESET_H
-#define _POWERTV_POWERTV_RESET_H
-extern void mips_reboot_setup(void);
-#endif
diff --git a/arch/mips/powertv/time.c b/arch/mips/powertv/time.c
deleted file mode 100644
index f38b0d45eca..00000000000
--- a/arch/mips/powertv/time.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Setting up the clock on the MIPS boards.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/interrupts.h>
-#include <asm/time.h>
-
-#include "powertv-clock.h"
-
-unsigned int get_c0_compare_int(void)
-{
- return irq_mips_timer;
-}
-
-void __init plat_time_init(void)
-{
- powertv_clocksource_init();
-}
diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
index 424f03496d1..4a296655f44 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -15,23 +15,18 @@ choice
config SOC_RT288X
bool "RT288x"
+ select MIPS_L1_CACHE_SHIFT_4
config SOC_RT305X
bool "RT305x"
select USB_ARCH_HAS_HCD
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
config SOC_RT3883
bool "RT3883"
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
select HW_HAS_PCI
config SOC_MT7620
bool "MT7620"
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
endchoice
diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c
index cc17566d193..24bf057a361 100644
--- a/arch/mips/ralink/cevt-rt3352.c
+++ b/arch/mips/ralink/cevt-rt3352.c
@@ -138,7 +138,7 @@ static void __init ralink_systick_init(struct device_node *np)
clockevents_register_device(&systick.dev);
- pr_info("%s: runing - mult: %d, shift: %d\n",
+ pr_info("%s: running - mult: %d, shift: %d\n",
np->name, systick.dev.mult, systick.dev.shift);
}
diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c
index bba0cdfd83b..5d0983d4716 100644
--- a/arch/mips/ralink/clk.c
+++ b/arch/mips/ralink/clk.c
@@ -26,7 +26,7 @@ void ralink_clk_add(const char *dev, unsigned long rate)
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
if (!clk)
- panic("failed to add clock\n");
+ panic("failed to add clock");
clk->cl.dev_id = dev;
clk->cl.clk = clk;
diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts
index 35eb874ab7f..709f58132f5 100644
--- a/arch/mips/ralink/dts/mt7620a_eval.dts
+++ b/arch/mips/ralink/dts/mt7620a_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink MT7620A evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts
index 322d7002595..0a685db093d 100644
--- a/arch/mips/ralink/dts/rt2880_eval.dts
+++ b/arch/mips/ralink/dts/rt2880_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink RT2880 evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x8000000 0x2000000>;
};
diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts
index 0ac73ea2819..ec9e9a03554 100644
--- a/arch/mips/ralink/dts/rt3052_eval.dts
+++ b/arch/mips/ralink/dts/rt3052_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink RT3052 evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/mips/ralink/dts/rt3883_eval.dts b/arch/mips/ralink/dts/rt3883_eval.dts
index 2fa6b330bf4..e8df21a5d10 100644
--- a/arch/mips/ralink/dts/rt3883_eval.dts
+++ b/arch/mips/ralink/dts/rt3883_eval.dts
@@ -7,6 +7,7 @@
model = "Ralink RT3883 evaluation board";
memory@0 {
+ device_type = "memory";
reg = <0x0 0x2000000>;
};
diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
index d217509e530..a3ad56c2372 100644
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
@@ -350,7 +350,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
name = "MT7620A";
soc_info->compatible = "ralink,mt7620a-soc";
} else {
- panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+ panic("mt7620: unknown SoC, n0:%08x n1:%08x", n0, n1);
}
rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
index ce38d11f9da..251395210e2 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -21,14 +21,13 @@
#include <asm/reboot.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
+#include <asm/prom.h>
#include "common.h"
__iomem void *rt_sysc_membase;
__iomem void *rt_memc_membase;
-extern struct boot_param_header __dtb_start;
-
__iomem void *plat_of_remap_node(const char *node)
{
struct resource res;
@@ -51,30 +50,7 @@ __iomem void *plat_of_remap_node(const char *node)
void __init device_tree_init(void)
{
- unsigned long base, size;
- void *fdt_copy;
-
- if (!initial_boot_params)
- return;
-
- base = virt_to_phys((void *)initial_boot_params);
- size = be32_to_cpu(initial_boot_params->totalsize);
-
- /* Before we do anything, lets reserve the dt blob */
- reserve_bootmem(base, size, BOOTMEM_DEFAULT);
-
- /* The strings in the flattened tree are referenced directly by the
- * device tree, so copy the flattened device tree from init memory
- * to regular memory.
- */
- fdt_copy = alloc_bootmem(size);
- memcpy(fdt_copy, initial_boot_params, size);
- initial_boot_params = fdt_copy;
-
- unflatten_device_tree();
-
- /* free the space reserved for the dt blob */
- free_bootmem(base, size);
+ unflatten_and_copy_device_tree();
}
void __init plat_mem_setup(void)
@@ -85,7 +61,7 @@ void __init plat_mem_setup(void)
* Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing
*/
- __dt_setup_arch(&__dtb_start);
+ __dt_setup_arch(__dtb_start);
if (soc_info.mem_size)
add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M,
@@ -108,7 +84,7 @@ static int __init plat_of_setup(void)
strncpy(of_ids[1].compatible, "palmbus", len);
if (of_platform_populate(NULL, of_ids, NULL, NULL))
- panic("failed to populate DT\n");
+ panic("failed to populate DT");
/* make sure ithat the reset controller is setup early */
ralink_rst_init();
diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
index ca7ee3a3379..bb82a82da9e 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -276,7 +276,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
name = "RT5350";
soc_info->compatible = "ralink,rt5350-soc";
} else {
- panic("rt305x: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+ panic("rt305x: unknown SoC, n0:%08x n1:%08x", n0, n1);
}
id = __raw_readl(sysc + SYSC_REG_CHIP_ID);
diff --git a/arch/mips/ralink/timer.c b/arch/mips/ralink/timer.c
index e49241a2c39..e38692a44e6 100644
--- a/arch/mips/ralink/timer.c
+++ b/arch/mips/ralink/timer.c
@@ -126,7 +126,7 @@ static int rt_timer_probe(struct platform_device *pdev)
return -ENOENT;
}
- rt->membase = devm_request_and_ioremap(&pdev->dev, res);
+ rt->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rt->membase))
return PTR_ERR(rt->membase);
@@ -147,7 +147,7 @@ static int rt_timer_probe(struct platform_device *pdev)
rt_timer_config(rt, 2);
rt_timer_enable(rt);
- dev_info(&pdev->dev, "maximum frequncy is %luHz\n", rt->timer_freq);
+ dev_info(&pdev->dev, "maximum frequency is %luHz\n", rt->timer_freq);
return 0;
}
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
index ab0e379dc7e..8e52446286c 100644
--- a/arch/mips/sgi-ip22/ip22-gio.c
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -19,6 +19,9 @@ static struct {
} gio_name_table[] = {
{ .name = "SGI Impact", .id = 0x10 },
{ .name = "Phobos G160", .id = 0x35 },
+ { .name = "Phobos G130", .id = 0x36 },
+ { .name = "Phobos G100", .id = 0x37 },
+ { .name = "Set Engineering GFE", .id = 0x38 },
/* fake IDs */
{ .name = "SGI Newport", .id = 0x7e },
{ .name = "SGI GR2/GR3", .id = 0x7f },
@@ -293,7 +296,16 @@ static int ip22_gio_id(unsigned long addr, u32 *res)
* data matches
*/
ptr8 = (void *)CKSEG1ADDR(addr + 3);
- get_dbe(tmp8, ptr8);
+ if (get_dbe(tmp8, ptr8)) {
+ /*
+ * 32bit access worked, but 8bit doesn't
+ * so we don't see phantom reads on
+ * a pipelined bus, but a real card which
+ * doesn't support 8 bit reads
+ */
+ *res = tmp32;
+ return 1;
+ }
ptr16 = (void *)CKSEG1ADDR(addr + 2);
get_dbe(tmp16, ptr16);
if (tmp8 == (tmp16 & 0xff) &&
@@ -324,7 +336,7 @@ static int ip22_is_gr2(unsigned long addr)
}
-static void ip22_check_gio(int slotno, unsigned long addr)
+static void ip22_check_gio(int slotno, unsigned long addr, int irq)
{
const char *name = "Unknown";
struct gio_device *gio_dev;
@@ -338,9 +350,9 @@ static void ip22_check_gio(int slotno, unsigned long addr)
else {
if (!ip22_gio_id(addr, &tmp)) {
/*
- * no GIO signature at start address of slot, but
- * Newport doesn't have one, so let's check usea
- * status register
+ * no GIO signature at start address of slot
+ * since Newport doesn't have one, we check if
+ * user status register is readable
*/
if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp))
tmp = 0x7e;
@@ -369,6 +381,7 @@ static void ip22_check_gio(int slotno, unsigned long addr)
gio_dev->resource.start = addr;
gio_dev->resource.end = addr + 0x3fffff;
gio_dev->resource.flags = IORESOURCE_MEM;
+ gio_dev->irq = irq;
dev_set_name(&gio_dev->dev, "%d", slotno);
gio_device_register(gio_dev);
} else
@@ -408,16 +421,17 @@ int __init ip22_gio_init(void)
request_resource(&iomem_resource, &gio_bus_resource);
printk(KERN_INFO "GIO: Probing bus...\n");
- if (ip22_is_fullhouse() ||
- !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) {
- /* Indigo2 and ChallengeS */
- ip22_check_gio(0, GIO_SLOT_GFX_BASE);
- ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
+ if (ip22_is_fullhouse()) {
+ /* Indigo2 */
+ ip22_check_gio(0, GIO_SLOT_GFX_BASE, SGI_GIO_1_IRQ);
+ ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIO_1_IRQ);
} else {
- /* Indy */
- ip22_check_gio(0, GIO_SLOT_GFX_BASE);
- ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
- ip22_check_gio(2, GIO_SLOT_EXP1_BASE);
+ /* Indy/Challenge S */
+ if (get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1]))
+ ip22_check_gio(0, GIO_SLOT_GFX_BASE,
+ SGI_GIO_0_IRQ);
+ ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIOEXP0_IRQ);
+ ip22_check_gio(2, GIO_SLOT_EXP1_BASE, SGI_GIOEXP1_IRQ);
}
} else
device_unregister(&gio_bus);
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index 3db64d51798..c66889fc491 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -119,9 +119,14 @@ static void indy_local0_irqdispatch(void)
} else
irq = lc0msk_to_irqnr[mask];
- /* if irq == 0, then the interrupt has already been cleared */
+ /*
+ * workaround for INT2 bug; if irq == 0, INT2 has seen a fifo full
+ * irq, but failed to latch it into status register
+ */
if (irq)
do_IRQ(irq);
+ else
+ do_IRQ(SGINT_LOCAL0 + 0);
}
static void indy_local1_irqdispatch(void)
@@ -148,7 +153,7 @@ static void __irq_entry indy_buserror_irq(void)
int irq = SGI_BUSERR_IRQ;
irq_enter();
- kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ kstat_incr_irq_this_cpu(irq);
ip22_be_interrupt(irq);
irq_exit();
}
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index 60719244933..045aa89f28d 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -123,7 +123,7 @@ void __irq_entry indy_8254timer_irq(void)
char c;
irq_enter();
- kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ kstat_incr_irq_this_cpu(irq);
printk(KERN_ALERT "Oops, got 8254 interrupt.\n");
ArcRead(0, &c, 1, &cnt);
ArcEnterInteractiveMode();
diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
index b952d5b1af8..45fdfbcbd4c 100644
--- a/arch/mips/sgi-ip27/ip27-console.c
+++ b/arch/mips/sgi-ip27/ip27-console.c
@@ -5,7 +5,6 @@
*
* Copyright (C) 2001, 2002 Ralf Baechle
*/
-#include <linux/init.h>
#include <asm/page.h>
#include <asm/sn/addrs.h>
diff --git a/arch/mips/sgi-ip27/ip27-irq-pci.c b/arch/mips/sgi-ip27/ip27-irq-pci.c
index ec22ec5600f..2a1c40784bd 100644
--- a/arch/mips/sgi-ip27/ip27-irq-pci.c
+++ b/arch/mips/sgi-ip27/ip27-irq-pci.c
@@ -8,7 +8,6 @@
#undef DEBUG
-#include <linux/init.h>
#include <linux/irq.h>
#include <linux/errno.h>
#include <linux/signal.h>
diff --git a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c
index 7afe1468800..c873d62ff08 100644
--- a/arch/mips/sgi-ip27/ip27-klconfig.c
+++ b/arch/mips/sgi-ip27/ip27-klconfig.c
@@ -2,7 +2,6 @@
* Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
index f4ea8aa79ba..f9ae6a8fa7c 100644
--- a/arch/mips/sgi-ip27/ip27-smp.c
+++ b/arch/mips/sgi-ip27/ip27-smp.c
@@ -186,10 +186,6 @@ static void ip27_smp_finish(void)
local_irq_enable();
}
-static void __init ip27_cpus_done(void)
-{
-}
-
/*
* Launch a slave into smp_bootstrap(). It doesn't take an argument, and we
* set sp to the kernel stack of the newly created idle process, gp to the proc
@@ -236,7 +232,6 @@ struct plat_smp_ops ip27_smp_ops = {
.send_ipi_mask = ip27_send_ipi_mask,
.init_secondary = ip27_init_secondary,
.smp_finish = ip27_smp_finish,
- .cpus_done = ip27_cpus_done,
.boot_secondary = ip27_boot_secondary,
.smp_setup = ip27_smp_setup,
.prepare_cpus = ip27_prepare_cpus,
diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c
index d59b820f528..20f582a2137 100644
--- a/arch/mips/sgi-ip27/ip27-xtalk.c
+++ b/arch/mips/sgi-ip27/ip27-xtalk.c
@@ -7,7 +7,6 @@
* Generic XTALK initialization code
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <asm/sn/types.h>
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 09d6e16a70f..373fbbc8425 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -95,7 +95,7 @@ static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask,
u64 cur_ints;
unsigned long flags;
- i = cpumask_first(mask);
+ i = cpumask_first_and(mask, cpu_online_mask);
/* Convert logical CPU to physical CPU */
cpu = cpu_logical_map(i);
@@ -347,19 +347,8 @@ asmlinkage void plat_irq_dispatch(void)
unsigned int cpu = smp_processor_id();
unsigned int pending;
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- /* Set compare to count to silence count/compare timer interrupts */
- write_c0_compare(read_c0_count());
-#endif
-
pending = read_c0_cause() & read_c0_status();
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
- sbprof_cpu_intr();
- else
-#endif
-
if (pending & CAUSEF_IP4)
do_IRQ(K_BCM1480_INT_TIMER_0 + cpu);
#ifdef CONFIG_SMP
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
index 05ed92c92b6..8e2e04f7787 100644
--- a/arch/mips/sibyte/bcm1480/setup.c
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -22,6 +22,7 @@
#include <linux/string.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
@@ -119,7 +120,7 @@ void __init bcm1480_setup(void)
uint64_t sys_rev;
int plldiv;
- sb1_pass = read_c0_prid() & 0xff;
+ sb1_pass = read_c0_prid() & PRID_REV_MASK;
sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
soc_type = SYS_SOC_TYPE(sys_rev);
part_type = G_SYS_PART(sys_rev);
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index 54e2c4de15c..af7d44edd9a 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -115,13 +115,6 @@ static void bcm1480_smp_finish(void)
}
/*
- * Final cleanup after all secondaries booted
- */
-static void bcm1480_cpus_done(void)
-{
-}
-
-/*
* Setup the PC, SP, and GP of a secondary processor and start it
* running!
*/
@@ -170,7 +163,6 @@ struct plat_smp_ops bcm1480_smp_ops = {
.send_ipi_mask = bcm1480_send_ipi_mask,
.init_secondary = bcm1480_init_secondary,
.smp_finish = bcm1480_smp_finish,
- .cpus_done = bcm1480_cpus_done,
.boot_secondary = bcm1480_boot_secondary,
.smp_setup = bcm1480_smp_setup,
.prepare_cpus = bcm1480_prepare_cpus,
@@ -182,7 +174,7 @@ void bcm1480_mailbox_interrupt(void)
int irq = K_BCM1480_INT_MBOX_0_0;
unsigned int action;
- kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ kstat_incr_irq_this_cpu(irq);
/* Load the mailbox register to figure out what we're supposed to do */
action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index fca0cdb9950..6d8dba5cf34 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -88,7 +88,7 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
u64 cur_ints;
unsigned long flags;
- i = cpumask_first(mask);
+ i = cpumask_first_and(mask, cpu_online_mask);
/* Convert logical CPU to physical CPU */
cpu = cpu_logical_map(i);
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index a14bd4cb0bc..3c02b2a77ae 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -22,6 +22,7 @@
#include <linux/string.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
@@ -182,7 +183,7 @@ void __init sb1250_setup(void)
int plldiv;
int bad_config = 0;
- sb1_pass = read_c0_prid() & 0xff;
+ sb1_pass = read_c0_prid() & PRID_REV_MASK;
sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
soc_type = SYS_SOC_TYPE(sys_rev);
soc_pass = G_SYS_REVISION(sys_rev);
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index d7b942db0ea..c0c4b3f88a0 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -103,13 +103,6 @@ static void sb1250_smp_finish(void)
}
/*
- * Final cleanup after all secondaries booted
- */
-static void sb1250_cpus_done(void)
-{
-}
-
-/*
* Setup the PC, SP, and GP of a secondary processor and start it
* running!
*/
@@ -158,7 +151,6 @@ struct plat_smp_ops sb_smp_ops = {
.send_ipi_mask = sb1250_send_ipi_mask,
.init_secondary = sb1250_init_secondary,
.smp_finish = sb1250_smp_finish,
- .cpus_done = sb1250_cpus_done,
.boot_secondary = sb1250_boot_secondary,
.smp_setup = sb1250_smp_setup,
.prepare_cpus = sb1250_prepare_cpus,
@@ -170,7 +162,7 @@ void sb1250_mailbox_interrupt(void)
int irq = K_INT_MBOX_0;
unsigned int action;
- kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ kstat_incr_irq_this_cpu(irq);
/* Load the mailbox register to figure out what we're supposed to do */
action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 41707a245de..3462c831d0e 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -134,8 +134,6 @@ void __init plat_mem_setup(void)
#error invalid SiByte board configuration
#endif
- panic_timeout = 5; /* For debug. */
-
board_be_handler = swarm_be_handler;
if (xicor_probe())
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 5b09b3544ed..efad85c8c82 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -25,6 +25,7 @@
#endif
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/io.h>
#include <asm/reboot.h>
#include <asm/sni.h>
@@ -173,7 +174,7 @@ void __init plat_mem_setup(void)
system_type = "RM300-Cxx";
break;
case SNI_BRD_PCI_DESKTOP:
- switch (read_c0_prid() & 0xff00) {
+ switch (read_c0_prid() & PRID_IMP_MASK) {
case PRID_IMP_R4600:
case PRID_IMP_R4700:
system_type = "RM200-C20";
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 2b0b83c171e..dd2cf25b5ae 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -309,8 +309,8 @@ static void __init preprocess_cmdline(void)
txx9_board_vec = find_board_byname(str + 6);
continue;
} else if (strncmp(str, "masterclk=", 10) == 0) {
- unsigned long val;
- if (strict_strtoul(str + 10, 10, &val) == 0)
+ unsigned int val;
+ if (kstrtouint(str + 10, 10, &val) == 0)
txx9_master_clock = val;
continue;
} else if (strcmp(str, "icdisable") == 0) {