Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 May 2016 17:02:26 +0000 (10:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 May 2016 17:02:26 +0000 (10:02 -0700)
Pull MIPS updates from Ralf Baechle:
 "This is the main pull request for MIPS for 4.7.  Here's the summary of
  the changes:

   - ATH79: Support for DTB passuing using the UHI boot protocol
   - ATH79: Remove support for builtin DTB.
   - ATH79: Add zboot debug serial support.
   - ATH79: Add initial support for Dragino MS14 (Dragine 2), Onion Omega
            and DPT-Module.
   - ATH79: Update devicetree clock support for AR9132 and AR9331.
   - ATH79: Cleanup the DT code.
   - ATH79: Support newer SOCs in ath79_ddr_ctrl_init.
   - ATH79: Fix regression in PCI window initialization.
   - BCM47xx: Move SPROM driver to drivers/firmware/
   - BCM63xx: Enable partition parser in defconfig.
   - BMIPS: BMIPS5000 has I cache filing from D cache
   - BMIPS: BMIPS: Add cpu-feature-overrides.h
   - BMIPS: Add Whirlwind support
   - BMIPS: Adjust mips-hpt-frequency for BCM7435
   - BMIPS: Remove maxcpus from BCM97435SVMB DTS
   - BMIPS: Add missing 7038 L1 register cells to BCM7435
   - BMIPS: Various tweaks to initialization code.
   - BMIPS: Enable partition parser in defconfig.
   - BMIPS: Cache tweaks.
   - BMIPS: Add UART, I2C and SATA devices to DT.
   - BMIPS: Add BCM6358 and BCM63268support
   - BMIPS: Add device tree example for BCM6358.
   - BMIPS: Improve Improve BCM6328 and BCM6368 device trees
   - Lantiq: Add support for device tree file from boot loader
   - Lantiq: Allow build with no built-in DT.
   - Loongson 3: Reserve 32MB for RS780E integrated GPU.
   - Loongson 3: Fix build error after ld-version.sh modification
   - Loongson 3: Move chipset ACPI code from drivers to arch.
   - Loongson 3: Speedup irq processing.
   - Loongson 3: Add basic Loongson 3A support.
   - Loongson 3: Set cache flush handlers to nop.
   - Loongson 3: Invalidate special TLBs when needed.
   - Loongson 3: Fast TLB refill handler.
   - MT7620: Fallback strategy for invalid syscfg0.
   - Netlogic: Fix CP0_EBASE redefinition warnings
   - Octeon: Initialization fixes
   - Octeon: Add DTS files for the D-Link DSR-1000N and EdgeRouter Lite
   - Octeon: Enable add Octeon-drivers in cavium_octeon_defconfig
   - Octeon: Correctly handle endian-swapped initramfs images.
   - Octeon: Support CN73xx, CN75xx and CN78xx.
   - Octeon: Remove dead code from cvmx-sysinfo.
   - Octeon: Extend number of supported CPUs past 32.
   - Octeon: Remove some code limiting NR_IRQS to 255.
   - Octeon: Simplify octeon_irq_ciu_gpio_set_type.
   - Octeon: Mark some functions __init in smp.c
   - Octeon: Octeon: Add Octeon III CN7xxx interface detection
   - PIC32: Add serial driver and bindings for it.
   - PIC32: Add PIC32 deadman timer driver and bindings.
   - PIC32: Add PIC32 clock timer driver and bindings.
   - Pistachio: Determine SoC revision during boot
   - Sibyte: Fix Kconfig dependencies of SIBYTE_BUS_WATCHER.
   - Sibyte: Strip redundant comments from bcm1480_regs.h.
   - Panic immediately if panic_on_oops is set.
   - module: fix incorrect IS_ERR_VALUE macro usage.
   - module: Make consistent use of pr_*
   - Remove no longer needed work_on_cpu() call.
   - Remove CONFIG_IPV6_PRIVACY from defconfigs.
   - Fix registers of non-crashing CPUs in dumps.
   - Handle MIPSisms in new vmcore_elf32_check_arch.
   - Select CONFIG_HANDLE_DOMAIN_IRQ and make it work.
   - Allow RIXI to be used on non-R2 or R6 cores.
   - Reserve nosave data for hibernation
   - Fix siginfo.h to use strict POSIX types.
   - Don't unwind user mode with EVA.
   - Fix watchpoint restoration
   - Ptrace watchpoints for R6.
   - Sync icache when it fills from dcache
   - I6400 I-cache fills from dcache.
   - Various MSA fixes.
   - Cleanup MIPS_CPU_* definitions.
   - Signal: Move generic copy_siginfo to signal.h
   - Signal: Fix uapi include in exported asm/siginfo.h
   - Timer fixes for sake of KVM.
   - XPA TLB refill fixes.
   - Treat perf counter feature
   - Update John Crispin's email address
   - Add PIC32 watchdog and bindings.
   - Handle R10000 LL/SC bug in set_pte()
   - cpufreq: Various fixes for Longson1.
   - R6: Fix R2 emulation.
   - mathemu: Cosmetic fix to ADDIUPC emulation, plenty of other small fixes
   - ELF: ABI and FP fixes.
   - Allow for relocatable kernel and use that to support KASLR.
   - Fix CPC_BASE_ADDR mask
   - Plenty fo smp-cps, CM, R6 and M6250 fixes.
   - Make reset_control_ops const.
   - Fix kernel command line handling of leading whitespace.
   - Cleanups to cache handling.
   - Add brcm, bcm6345-l1-intc device tree bindings.
   - Use generic clkdev.h header
   - Remove CLK_IS_ROOT usage.
   - Misc small cleanups.
   - CM: Fix compilation error when !MIPS_CM
   - oprofile: Fix a preemption issue
   - Detect DSP ASE v3 support:1"

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (275 commits)
  MIPS: pic32mzda: fix getting timer clock rate.
  MIPS: ath79: fix regression in PCI window initialization
  MIPS: ath79: make ath79_ddr_ctrl_init() compatible for newer SoCs
  MIPS: Fix VZ probe gas errors with binutils <2.24
  MIPS: perf: Fix I6400 event numbers
  MIPS: DEC: Export `ioasic_ssr_lock' to modules
  MIPS: MSA: Fix a link error on `_init_msa_upper' with older GCC
  MIPS: CM: Fix compilation error when !MIPS_CM
  MIPS: Fix genvdso error on rebuild
  USB: ohci-jz4740: Remove obsolete driver
  MIPS: JZ4740: Probe OHCI platform device via DT
  MIPS: JZ4740: Qi LB60: Remove support for AVT2 variant
  MIPS: pistachio: Determine SoC revision during boot
  MIPS: BMIPS: Adjust mips-hpt-frequency for BCM7435
  mips: mt7620: fallback to SDRAM when syscfg0 does not have a valid value for the memory type
  MIPS: Prevent "restoration" of MSA context in non-MSA kernels
  MIPS: cevt-r4k: Dynamically calculate min_delta_ns
  MIPS: malta-time: Take seconds into account
  MIPS: malta-time: Start GIC count before syncing to RTC
  MIPS: Force CPUs to lose FP context during mode switches
  ...

358 files changed:
Documentation/devicetree/bindings/clock/microchip,pic32.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mips/brcm/soc.txt
Documentation/devicetree/bindings/mips/cavium/ciu3.txt [new file with mode: 0644]
Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/watchdog/microchip,pic32-dmt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/microchip,pic32-wdt.txt [new file with mode: 0644]
MAINTAINERS
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/alchemy/common/clock.c
arch/mips/ath79/Kconfig
arch/mips/ath79/clock.c
arch/mips/ath79/common.c
arch/mips/ath79/setup.c
arch/mips/bcm47xx/Makefile
arch/mips/bcm47xx/bcm47xx_private.h
arch/mips/bcm47xx/setup.c
arch/mips/bmips/Kconfig
arch/mips/bmips/setup.c
arch/mips/boot/compressed/Makefile
arch/mips/boot/dts/brcm/Makefile
arch/mips/boot/dts/brcm/bcm6328.dtsi
arch/mips/boot/dts/brcm/bcm6358.dtsi [new file with mode: 0644]
arch/mips/boot/dts/brcm/bcm6368.dtsi
arch/mips/boot/dts/brcm/bcm7125.dtsi
arch/mips/boot/dts/brcm/bcm7346.dtsi
arch/mips/boot/dts/brcm/bcm7358.dtsi
arch/mips/boot/dts/brcm/bcm7360.dtsi
arch/mips/boot/dts/brcm/bcm7362.dtsi
arch/mips/boot/dts/brcm/bcm7420.dtsi
arch/mips/boot/dts/brcm/bcm7425.dtsi
arch/mips/boot/dts/brcm/bcm7435.dtsi
arch/mips/boot/dts/brcm/bcm96358nb4ser.dts [new file with mode: 0644]
arch/mips/boot/dts/brcm/bcm96368mvwg.dts
arch/mips/boot/dts/brcm/bcm97125cbmb.dts
arch/mips/boot/dts/brcm/bcm97360svmb.dts
arch/mips/boot/dts/brcm/bcm97420c.dts
arch/mips/boot/dts/brcm/bcm97425svmb.dts
arch/mips/boot/dts/brcm/bcm97435svmb.dts
arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts [new file with mode: 0644]
arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts
arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi [new file with mode: 0644]
arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts [new file with mode: 0644]
arch/mips/boot/dts/ingenic/jz4740.dtsi
arch/mips/boot/dts/lantiq/easy50712.dts
arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi [deleted file]
arch/mips/boot/dts/pic32/pic32mzda.dtsi
arch/mips/boot/dts/pic32/pic32mzda_sk.dts
arch/mips/boot/dts/qca/Makefile
arch/mips/boot/dts/qca/ar9132.dtsi
arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts
arch/mips/boot/dts/qca/ar9331.dtsi [new file with mode: 0644]
arch/mips/boot/dts/qca/ar9331_dpt_module.dts [new file with mode: 0644]
arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts [new file with mode: 0644]
arch/mips/boot/dts/qca/ar9331_omega.dts [new file with mode: 0644]
arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts [new file with mode: 0644]
arch/mips/boot/tools/.gitignore [new file with mode: 0644]
arch/mips/boot/tools/Makefile [new file with mode: 0644]
arch/mips/boot/tools/relocs.c [new file with mode: 0644]
arch/mips/boot/tools/relocs.h [new file with mode: 0644]
arch/mips/boot/tools/relocs_32.c [new file with mode: 0644]
arch/mips/boot/tools/relocs_64.c [new file with mode: 0644]
arch/mips/boot/tools/relocs_main.c [new file with mode: 0644]
arch/mips/cavium-octeon/csrc-octeon.c
arch/mips/cavium-octeon/executive/cvmx-helper.c
arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
arch/mips/cavium-octeon/executive/octeon-model.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/cavium-octeon/octeon-platform.c
arch/mips/cavium-octeon/setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/configs/bcm47xx_defconfig
arch/mips/configs/bcm63xx_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/bmips_be_defconfig
arch/mips/configs/cavium_octeon_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/jazz_defconfig
arch/mips/configs/lemote2f_defconfig
arch/mips/configs/loongson1b_defconfig [moved from arch/mips/configs/ls1b_defconfig with 84% similarity]
arch/mips/configs/mtx1_defconfig
arch/mips/configs/nlm_xlp_defconfig
arch/mips/configs/nlm_xlr_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/dec/setup.c
arch/mips/include/asm/Kbuild
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/bitops.h
arch/mips/include/asm/bitrev.h [new file with mode: 0644]
arch/mips/include/asm/bmips.h
arch/mips/include/asm/bootinfo.h
arch/mips/include/asm/cacheflush.h
arch/mips/include/asm/cacheops.h
arch/mips/include/asm/clkdev.h [deleted file]
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/cpu-info.h
arch/mips/include/asm/cpu-type.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/hazards.h
arch/mips/include/asm/highmem.h
arch/mips/include/asm/io.h
arch/mips/include/asm/irq_regs.h
arch/mips/include/asm/irqflags.h
arch/mips/include/asm/kvm_host.h
arch/mips/include/asm/llsc.h [new file with mode: 0644]
arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h [new file with mode: 0644]
arch/mips/include/asm/mach-bmips/ioremap.h [new file with mode: 0644]
arch/mips/include/asm/mach-jz4740/platform.h
arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
arch/mips/include/asm/mach-lantiq/lantiq.h
arch/mips/include/asm/mach-lantiq/lantiq_platform.h
arch/mips/include/asm/mach-lantiq/xway/irq.h
arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
arch/mips/include/asm/mach-loongson32/cpufreq.h
arch/mips/include/asm/mach-loongson32/dma.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson32/irq.h
arch/mips/include/asm/mach-loongson32/loongson1.h
arch/mips/include/asm/mach-loongson32/nand.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson32/platform.h
arch/mips/include/asm/mach-loongson32/regs-clk.h
arch/mips/include/asm/mach-loongson32/regs-mux.h
arch/mips/include/asm/mach-loongson32/regs-pwm.h
arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
arch/mips/include/asm/mach-ralink/mt7620.h
arch/mips/include/asm/mach-ralink/mt7621.h
arch/mips/include/asm/mach-ralink/pinmux.h
arch/mips/include/asm/mach-ralink/ralink_regs.h
arch/mips/include/asm/mach-ralink/rt288x.h
arch/mips/include/asm/mach-ralink/rt305x.h
arch/mips/include/asm/mips-cm.h
arch/mips/include/asm/mips-cpc.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/msa.h
arch/mips/include/asm/octeon/cvmx-bootinfo.h
arch/mips/include/asm/octeon/cvmx-ciu3-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-coremask.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-fpa-defs.h
arch/mips/include/asm/octeon/cvmx-mio-defs.h
arch/mips/include/asm/octeon/cvmx-sysinfo.h
arch/mips/include/asm/octeon/cvmx.h
arch/mips/include/asm/octeon/octeon-feature.h
arch/mips/include/asm/octeon/octeon-model.h
arch/mips/include/asm/octeon/octeon.h
arch/mips/include/asm/pci.h
arch/mips/include/asm/pgtable-32.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/asm/pgtable-bits.h
arch/mips/include/asm/pgtable.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/seccomp.h
arch/mips/include/asm/sibyte/bcm1480_regs.h
arch/mips/include/asm/signal.h
arch/mips/include/asm/smp-cps.h
arch/mips/include/asm/switch_to.h
arch/mips/include/asm/uasm.h
arch/mips/include/asm/watch.h
arch/mips/include/uapi/asm/inst.h
arch/mips/include/uapi/asm/siginfo.h
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/platform.c
arch/mips/kernel/Makefile
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/binfmt_elfn32.c
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/bmips_5xxx_init.S [new file with mode: 0644]
arch/mips/kernel/bmips_vec.S
arch/mips/kernel/branch.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cps-vec.S
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/crash.c
arch/mips/kernel/genex.S
arch/mips/kernel/head.S
arch/mips/kernel/idle.c
arch/mips/kernel/mips-r2-to-r6-emul.c
arch/mips/kernel/module-rela.c
arch/mips/kernel/module.c
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/pm-cps.c
arch/mips/kernel/pm.c
arch/mips/kernel/proc.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/relocate.c [new file with mode: 0644]
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/smp-bmips.c
arch/mips/kernel/smp-cps.c
arch/mips/kernel/smp.c
arch/mips/kernel/spram.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/kernel/watch.c
arch/mips/kvm/emulate.c
arch/mips/kvm/locore.S
arch/mips/kvm/tlb.c
arch/mips/kvm/trap_emul.c
arch/mips/lantiq/Kconfig
arch/mips/lantiq/Makefile
arch/mips/lantiq/clk.c
arch/mips/lantiq/clk.h
arch/mips/lantiq/early_printk.c
arch/mips/lantiq/falcon/prom.c
arch/mips/lantiq/falcon/reset.c
arch/mips/lantiq/falcon/sysctrl.c
arch/mips/lantiq/irq.c
arch/mips/lantiq/prom.c
arch/mips/lantiq/prom.h
arch/mips/lantiq/xway/clk.c
arch/mips/lantiq/xway/dcdc.c
arch/mips/lantiq/xway/dma.c
arch/mips/lantiq/xway/gptu.c
arch/mips/lantiq/xway/prom.c
arch/mips/lantiq/xway/reset.c
arch/mips/lantiq/xway/sysctrl.c
arch/mips/lantiq/xway/vmmc.c
arch/mips/lantiq/xway/xrx200_phy_fw.c
arch/mips/lib/dump_tlb.c
arch/mips/lib/memset.S
arch/mips/lib/r3k_dump_tlb.c
arch/mips/loongson32/common/platform.c
arch/mips/loongson32/common/reset.c
arch/mips/loongson32/common/time.c
arch/mips/loongson32/ls1b/board.c
arch/mips/loongson64/Platform
arch/mips/loongson64/common/env.c
arch/mips/loongson64/loongson-3/Makefile
arch/mips/loongson64/loongson-3/acpi_init.c [moved from drivers/platform/mips/acpi_init.c with 100% similarity]
arch/mips/loongson64/loongson-3/irq.c
arch/mips/loongson64/loongson-3/numa.c
arch/mips/loongson64/loongson-3/smp.c
arch/mips/math-emu/Makefile
arch/mips/math-emu/cp1emu.c
arch/mips/math-emu/dp_maddf.c
arch/mips/math-emu/dp_msubf.c [deleted file]
arch/mips/math-emu/dp_mul.c
arch/mips/math-emu/dsemul.c
arch/mips/math-emu/ieee754dp.c
arch/mips/math-emu/ieee754dp.h
arch/mips/math-emu/ieee754int.h
arch/mips/math-emu/ieee754sp.c
arch/mips/math-emu/ieee754sp.h
arch/mips/math-emu/sp_add.c
arch/mips/math-emu/sp_maddf.c
arch/mips/math-emu/sp_msubf.c [deleted file]
arch/mips/math-emu/sp_sub.c
arch/mips/mm/c-r4k.c
arch/mips/mm/cache.c
arch/mips/mm/dma-default.c
arch/mips/mm/init.c
arch/mips/mm/page.c
arch/mips/mm/sc-mips.c
arch/mips/mm/tlb-r3k.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlb-r8k.c
arch/mips/mm/tlbex.c
arch/mips/mm/uasm-mips.c
arch/mips/mm/uasm.c
arch/mips/mti-malta/malta-setup.c
arch/mips/mti-malta/malta-time.c
arch/mips/mti-sead3/sead3-setup.c
arch/mips/netlogic/common/reset.S
arch/mips/netlogic/common/smpboot.S
arch/mips/netlogic/xlp/nlm_hal.c
arch/mips/netlogic/xlr/setup.c
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/fixup-lantiq.c
arch/mips/pci/ops-lantiq.c
arch/mips/pci/pci-alchemy.c
arch/mips/pci/pci-ip32.c
arch/mips/pci/pci-lantiq.c
arch/mips/pci/pci-lantiq.h
arch/mips/pci/pci-mt7620.c
arch/mips/pci/pci-rt2880.c
arch/mips/pci/pci.c
arch/mips/pic32/pic32mzda/time.c
arch/mips/pistachio/init.c
arch/mips/pmcs-msp71xx/msp_setup.c
arch/mips/pnx833x/common/setup.c
arch/mips/ralink/Makefile
arch/mips/ralink/bootrom.c
arch/mips/ralink/cevt-rt3352.c
arch/mips/ralink/clk.c
arch/mips/ralink/common.h
arch/mips/ralink/ill_acc.c
arch/mips/ralink/irq-gic.c
arch/mips/ralink/irq.c
arch/mips/ralink/mt7620.c
arch/mips/ralink/mt7621.c
arch/mips/ralink/of.c
arch/mips/ralink/prom.c
arch/mips/ralink/reset.c
arch/mips/ralink/rt288x.c
arch/mips/ralink/rt305x.c
arch/mips/ralink/rt3883.c
arch/mips/ralink/timer-gic.c
arch/mips/ralink/timer.c
arch/mips/sibyte/Kconfig
arch/mips/vdso/Makefile
arch/mips/vr41xx/common/pmu.c
drivers/bus/brcmstb_gisb.c
drivers/bus/mips_cdmm.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/microchip/Makefile [new file with mode: 0644]
drivers/clk/microchip/clk-core.c [new file with mode: 0644]
drivers/clk/microchip/clk-core.h [new file with mode: 0644]
drivers/clk/microchip/clk-pic32mzda.c [new file with mode: 0644]
drivers/cpufreq/Makefile
drivers/cpufreq/loongson1-cpufreq.c [moved from drivers/cpufreq/ls1x-cpufreq.c with 65% similarity]
drivers/firmware/broadcom/Kconfig
drivers/firmware/broadcom/Makefile
drivers/firmware/broadcom/bcm47xx_sprom.c [moved from arch/mips/bcm47xx/sprom.c with 98% similarity]
drivers/irqchip/irq-mips-gic.c
drivers/platform/mips/Kconfig
drivers/platform/mips/Makefile
drivers/platform/mips/cpu_hwmon.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/pic32_uart.c [new file with mode: 0644]
drivers/tty/serial/pic32_uart.h [new file with mode: 0644]
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-jz4740.c [deleted file]
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/pic32-dmt.c [new file with mode: 0644]
drivers/watchdog/pic32-wdt.c [new file with mode: 0644]
fs/proc/vmcore.c
include/asm-generic/seccomp.h
include/asm-generic/siginfo.h
include/dt-bindings/clock/ath79-clk.h [new file with mode: 0644]
include/dt-bindings/clock/microchip,pic32-clock.h [new file with mode: 0644]
include/linux/bcm47xx_sprom.h [new file with mode: 0644]
include/linux/crash_dump.h
include/linux/irqchip/mips-gic.h
include/linux/signal.h
include/uapi/linux/serial_core.h
kernel/seccomp.c
scripts/ld-version.sh
tools/testing/selftests/seccomp/seccomp_bpf.c

diff --git a/Documentation/devicetree/bindings/clock/microchip,pic32.txt b/Documentation/devicetree/bindings/clock/microchip,pic32.txt
new file mode 100644 (file)
index 0000000..c93d88f
--- /dev/null
@@ -0,0 +1,39 @@
+Microchip PIC32 Clock Controller Binding
+----------------------------------------
+Microchip clock controller is consists of few oscillators, PLL, multiplexer
+and few divider modules.
+
+This binding uses common clock bindings.
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible: shall be "microchip,pic32mzda-clk".
+- reg: shall contain base address and length of clock registers.
+- #clock-cells: shall be 1.
+
+Optional properties:
+- microchip,pic32mzda-sosc: shall be added only if platform has
+  secondary oscillator connected.
+
+Example:
+       rootclk: clock-controller@1f801200 {
+               compatible = "microchip,pic32mzda-clk";
+               reg = <0x1f801200 0x200>;
+               #clock-cells = <1>;
+               /* optional */
+               microchip,pic32mzda-sosc;
+       };
+
+
+The clock consumer shall specify the desired clock-output of the clock
+controller (as defined in [2]) by specifying output-id in its "clock"
+phandle cell.
+[2] include/dt-bindings/clock/microchip,pic32-clock.h
+
+For example for UART2:
+uart2: serial@2 {
+       compatible = "microchip,pic32mzda-uart";
+       reg = <>;
+       interrupts = <>;
+       clocks = <&rootclk PB2CLK>;
+};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt
new file mode 100644 (file)
index 0000000..4040905
--- /dev/null
@@ -0,0 +1,57 @@
+Broadcom BCM6345-style Level 1 interrupt controller
+
+This block is a first level interrupt controller that is typically connected
+directly to one of the HW INT lines on each CPU.
+
+Key elements of the hardware design include:
+
+- 32, 64 or 128 incoming level IRQ lines
+
+- Most onchip peripherals are wired directly to an L1 input
+
+- A separate instance of the register set for each CPU, allowing individual
+  peripheral IRQs to be routed to any CPU
+
+- Contains one or more enable/status word pairs per CPU
+
+- No atomic set/clear operations
+
+- No polarity/level/edge settings
+
+- No FIFO or priority encoder logic; software is expected to read all
+  2-4 status words to determine which IRQs are pending
+
+Required properties:
+
+- compatible: should be "brcm,bcm<soc>-l1-intc", "brcm,bcm6345-l1-intc"
+- reg: specifies the base physical address and size of the registers;
+  the number of supported IRQs is inferred from the size argument
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: specifies the number of cells needed to encode an interrupt
+  source, should be 1.
+- interrupt-parent: specifies the phandle to the parent interrupt controller(s)
+  this one is cascaded from
+- interrupts: specifies the interrupt line(s) in the interrupt-parent controller
+  node; valid values depend on the type of parent interrupt controller
+
+If multiple reg ranges and interrupt-parent entries are present on an SMP
+system, the driver will allow IRQ SMP affinity to be set up through the
+/proc/irq/ interface.  In the simplest possible configuration, only one
+reg range and one interrupt-parent is needed.
+
+The driver operates in native CPU endian by default, there is no support for
+specifying an alternative endianness.
+
+Example:
+
+periph_intc: interrupt-controller@10000000 {
+        compatible = "brcm,bcm63168-l1-intc", "brcm,bcm6345-l1-intc";
+        reg = <0x10000020 0x20>,
+              <0x10000040 0x20>;
+
+        interrupt-controller;
+        #interrupt-cells = <1>;
+
+        interrupt-parent = <&cpu_intc>;
+        interrupts = <2>, <3>;
+};
index 7bab90cc4a7bf45ba42b8492605f8dd41e3ba6d2..4a7e030e4f9bae7880650d9fbb3afb79673a4f77 100644 (file)
@@ -4,7 +4,8 @@ Required properties:
 
 - compatible: "brcm,bcm3384", "brcm,bcm33843"
               "brcm,bcm3384-viper", "brcm,bcm33843-viper"
-              "brcm,bcm6328", "brcm,bcm6368",
+              "brcm,bcm6328", "brcm,bcm6358", "brcm,bcm6368",
+              "brcm,bcm63168", "brcm,bcm63268",
               "brcm,bcm7125", "brcm,bcm7346", "brcm,bcm7358", "brcm,bcm7360",
               "brcm,bcm7362", "brcm,bcm7420", "brcm,bcm7425"
 
diff --git a/Documentation/devicetree/bindings/mips/cavium/ciu3.txt b/Documentation/devicetree/bindings/mips/cavium/ciu3.txt
new file mode 100644 (file)
index 0000000..616862a
--- /dev/null
@@ -0,0 +1,27 @@
+* Central Interrupt Unit v3
+
+Properties:
+- compatible: "cavium,octeon-7890-ciu3"
+
+  Compatibility with 78XX and 73XX SOCs.
+
+- interrupt-controller:  This is an interrupt controller.
+
+- reg: The base address of the CIU's register bank.
+
+- #interrupt-cells: Must be <2>.  The first cell is source number.
+  The second cell indicates the triggering semantics, and may have a
+  value of either 4 for level semantics, or 1 for edge semantics.
+
+Example:
+       interrupt-controller@1010000000000 {
+               compatible = "cavium,octeon-7890-ciu3";
+               interrupt-controller;
+               /* Interrupts are specified by two parts:
+                * 1) Source number (20 significant bits)
+                * 2) Trigger type: (4 == level, 1 == edge)
+                */
+               #address-cells = <0>;
+               #interrupt-cells = <2>;
+               reg = <0x10100 0x00000000 0x0 0xb0000000>;
+       };
diff --git a/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt b/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
new file mode 100644 (file)
index 0000000..65b38bf
--- /dev/null
@@ -0,0 +1,29 @@
+* Microchip Universal Asynchronous Receiver Transmitter (UART)
+
+Required properties:
+- compatible: Should be "microchip,pic32mzda-uart"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+- clocks: Phandle to the clock.
+          See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+- pinctrl-names: A pinctrl state names "default" must be defined.
+- pinctrl-0: Phandle referencing pin configuration of the UART peripheral.
+             See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+Optional properties:
+- cts-gpios: CTS pin for UART
+
+Example:
+       uart1: serial@1f822000 {
+               compatible = "microchip,pic32mzda-uart";
+               reg = <0x1f822000 0x50>;
+               interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
+                       <113 IRQ_TYPE_LEVEL_HIGH>,
+                       <114 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&PBCLK2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_uart1
+                               &pinctrl_uart1_cts
+                               &pinctrl_uart1_rts>;
+               cts-gpios = <&gpio1 15 0>;
+       };
index 021bbe7866e0f5712e8c08d6ba3dff29362b59f7..316412dc79135a472886a331caa9ff4a22932bfe 100644 (file)
@@ -72,6 +72,8 @@ digilent      Diglent, Inc.
 dlg    Dialog Semiconductor
 dlink  D-Link Corporation
 dmo    Data Modul AG
+dptechnics     DPTechnics
+dragino        Dragino Technology Co., Limited
 ea     Embedded Artists AB
 ebv    EBV Elektronik
 edt    Emerging Display Technologies
@@ -176,6 +178,7 @@ nvidia      NVIDIA
 nxp    NXP Semiconductors
 okaya  Okaya Electric America, Inc.
 olimex OLIMEX Ltd.
+onion  Onion Corporation
 onnn   ON Semiconductor Corp.
 opencores      OpenCores.org
 option Option NV
diff --git a/Documentation/devicetree/bindings/watchdog/microchip,pic32-dmt.txt b/Documentation/devicetree/bindings/watchdog/microchip,pic32-dmt.txt
new file mode 100644 (file)
index 0000000..852f694
--- /dev/null
@@ -0,0 +1,19 @@
+* Microchip PIC32 Deadman Timer
+
+The deadman timer is used to reset the processor in the event of a software
+malfunction. It is a free-running instruction fetch timer, which is clocked
+whenever an instruction fetch occurs until a count match occurs.
+
+Required properties:
+- compatible: must be "microchip,pic32mzda-dmt".
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: phandle of parent clock (should be &PBCLK7).
+
+Example:
+
+       watchdog@1f800a00 {
+               compatible = "microchip,pic32mzda-dmt";
+               reg = <0x1f800a00 0x80>;
+               clocks = <&PBCLK7>;
+       };
diff --git a/Documentation/devicetree/bindings/watchdog/microchip,pic32-wdt.txt b/Documentation/devicetree/bindings/watchdog/microchip,pic32-wdt.txt
new file mode 100644 (file)
index 0000000..d140103
--- /dev/null
@@ -0,0 +1,18 @@
+* Microchip PIC32 Watchdog Timer
+
+When enabled, the watchdog peripheral can be used to reset the device if the
+WDT is not cleared periodically in software.
+
+Required properties:
+- compatible: must be "microchip,pic32mzda-wdt".
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: phandle of source clk. should be <&LPRC> clk.
+
+Example:
+
+       watchdog@1f800800 {
+               compatible = "microchip,pic32mzda-wdt";
+               reg = <0x1f800800 0x200>;
+               clocks = <&LPRC>;
+       };
index 3f14e1dffa6ac95f4cf9c18fd8d41e4aaefe7b06..ef8a56e04af6751f15d0933d9f039735bca178c5 100644 (file)
@@ -6491,7 +6491,7 @@ F:        net/l3mdev
 F:     include/net/l3mdev.h
 
 LANTIQ MIPS ARCHITECTURE
-M:     John Crispin <blogic@openwrt.org>
+M:     John Crispin <john@phrozen.org>
 L:     linux-mips@linux-mips.org
 S:     Maintained
 F:     arch/mips/lantiq
@@ -7332,6 +7332,15 @@ S:       Supported
 F:     Documentation/mips/
 F:     arch/mips/
 
+MIPS/LOONGSON1 ARCHITECTURE
+M:     Keguang Zhang <keguang.zhang@gmail.com>
+L:     linux-mips@linux-mips.org
+S:     Maintained
+F:     arch/mips/loongson32/
+F:     arch/mips/include/asm/mach-loongson32/
+F:     drivers/*/*loongson1*
+F:     drivers/*/*/*loongson1*
+
 MIROSOUND PCM20 FM RADIO RECEIVER DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     linux-media@vger.kernel.org
@@ -9251,7 +9260,7 @@ S:        Maintained
 F:     drivers/video/fbdev/aty/aty128fb.c
 
 RALINK MIPS ARCHITECTURE
-M:     John Crispin <blogic@openwrt.org>
+M:     John Crispin <john@phrozen.org>
 L:     linux-mips@linux-mips.org
 S:     Maintained
 F:     arch/mips/ralink
index d2ac1174ee17ab0c088c91cbf37151e855a46062..5663f411c22565b3ba9fa8e717a5230135698732 100644 (file)
@@ -62,6 +62,7 @@ config MIPS
        select HAVE_IRQ_TIME_ACCOUNTING
        select GENERIC_TIME_VSYSCALL
        select ARCH_CLOCKSOURCE_DATA
+       select HANDLE_DOMAIN_IRQ
 
 menu "Machine selection"
 
@@ -137,7 +138,7 @@ config ATH79
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_MIPS16
-       select SYS_SUPPORTS_ZBOOT
+       select SYS_SUPPORTS_ZBOOT_UART_PROM
        select USE_OF
        help
          Support for the Atheros AR71XX/AR724X/AR913X SoCs.
@@ -194,6 +195,7 @@ config BCM47XX
        select GPIOLIB
        select LEDS_GPIO_REGISTER
        select BCM47XX_NVRAM
+       select BCM47XX_SPROM
        help
         Support for BCM47XX based boards
 
@@ -471,6 +473,7 @@ config MIPS_MALTA
        select SYS_SUPPORTS_MULTITHREADING
        select SYS_SUPPORTS_SMARTMIPS
        select SYS_SUPPORTS_ZBOOT
+       select SYS_SUPPORTS_RELOCATABLE
        select USE_OF
        select ZONE_DMA32 if 64BIT
        select BUILTIN_DTB
@@ -505,6 +508,7 @@ config MIPS_SEAD3
        select MIPS_MSC
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_HAS_CPU_MIPS32_R2
+       select SYS_HAS_CPU_MIPS32_R6
        select SYS_HAS_CPU_MIPS64_R1
        select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
@@ -514,6 +518,7 @@ config MIPS_SEAD3
        select SYS_SUPPORTS_SMARTMIPS
        select SYS_SUPPORTS_MICROMIPS
        select SYS_SUPPORTS_MIPS16
+       select SYS_SUPPORTS_RELOCATABLE
        select USB_EHCI_BIG_ENDIAN_DESC
        select USB_EHCI_BIG_ENDIAN_MMIO
        select USE_OF
@@ -1153,6 +1158,13 @@ config ISA_DMA_API
 config HOLES_IN_ZONE
        bool
 
+config SYS_SUPPORTS_RELOCATABLE
+       bool
+       help
+        Selected if the platform supports relocating the kernel.
+        The platform must provide plat_get_fdt() if it selects CONFIG_USE_OF
+        to allow access to command line and entropy sources.
+
 #
 # Endianness selection.  Sufficiently obscure so many users don't know what to
 # answer,so we try hard to limit the available choices.  Also the use of a
@@ -1340,11 +1352,30 @@ config CPU_LOONGSON3
        select CPU_SUPPORTS_HUGEPAGES
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
+       select MIPS_PGD_C0_CONTEXT
        select GPIOLIB
        help
                The Loongson 3 processor implements the MIPS64R2 instruction
                set with many extensions.
 
+config LOONGSON3_ENHANCEMENT
+       bool "New Loongson 3 CPU Enhancements"
+       default n
+       select CPU_MIPSR2
+       select CPU_HAS_PREFETCH
+       depends on CPU_LOONGSON3
+       help
+         New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A
+         R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as
+         FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User
+         Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer),
+         Fast TLB refill support, etc.
+
+         This option enable those enhancements which are not probed at run
+         time. If you want a generic kernel to run on all Loongson 3 machines,
+         please say 'N' here. If you want a high-performance kernel to run on
+         new Loongson 3 machines only, please say 'Y' here.
+
 config CPU_LOONGSON2E
        bool "Loongson 2E"
        depends on SYS_HAS_CPU_LOONGSON2E
@@ -1373,6 +1404,8 @@ config CPU_LOONGSON1B
        bool "Loongson 1B"
        depends on SYS_HAS_CPU_LOONGSON1B
        select CPU_LOONGSON1
+       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select LEDS_GPIO_REGISTER
        help
          The Loongson 1B is a 32-bit SoC, which implements the MIPS32
          release 2 instruction set.
@@ -1671,6 +1704,7 @@ config CPU_XLP
        select CPU_HAS_PREFETCH
        select CPU_MIPSR2
        select CPU_SUPPORTS_HUGEPAGES
+       select MIPS_ASID_BITS_VARIABLE
        help
          Netlogic Microsystems XLP processors.
 endchoice
@@ -1796,6 +1830,7 @@ config CPU_BMIPS4380
        select MIPS_L1_CACHE_SHIFT_6
        select SYS_SUPPORTS_SMP
        select SYS_SUPPORTS_HOTPLUG_CPU
+       select CPU_HAS_RIXI
 
 config CPU_BMIPS5000
        bool
@@ -1803,10 +1838,12 @@ config CPU_BMIPS5000
        select MIPS_L1_CACHE_SHIFT_7
        select SYS_SUPPORTS_SMP
        select SYS_SUPPORTS_HOTPLUG_CPU
+       select CPU_HAS_RIXI
 
 config SYS_HAS_CPU_LOONGSON3
        bool
        select CPU_SUPPORTS_CPUFREQ
+       select CPU_HAS_RIXI
 
 config SYS_HAS_CPU_LOONGSON2E
        bool
@@ -1959,11 +1996,15 @@ config CPU_MIPSR1
 config CPU_MIPSR2
        bool
        default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
+       select CPU_HAS_RIXI
        select MIPS_SPRAM
 
 config CPU_MIPSR6
        bool
        default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
+       select CPU_HAS_RIXI
+       select HAVE_ARCH_BITREVERSE
+       select MIPS_ASID_BITS_VARIABLE
        select MIPS_SPRAM
 
 config EVA
@@ -1997,7 +2038,7 @@ config MIPS_PGD_C0_CONTEXT
 #
 config HARDWARE_WATCHPOINTS
        bool
-       default y if CPU_MIPSR1 || CPU_MIPSR2
+       default y if CPU_MIPSR1 || CPU_MIPSR2 || CPU_MIPSR6
 
 menu "Kernel type"
 
@@ -2040,6 +2081,16 @@ config KVM_GUEST_TIMER_FREQ
          emulation when determining guest CPU Frequency. Instead, the guest's
          timer frequency is specified directly.
 
+config MIPS_VA_BITS_48
+       bool "48 bits virtual memory"
+       depends on 64BIT
+       help
+         Support a maximum at least 48 bits of application virtual memory.
+         Default is 40 bits or less, depending on the CPU.
+         This option result in a small memory overhead for page tables.
+         This option is only supported with 16k and 64k page sizes.
+         If unsure, say N.
+
 choice
        prompt "Kernel page size"
        default PAGE_SIZE_4KB
@@ -2047,6 +2098,7 @@ choice
 config PAGE_SIZE_4KB
        bool "4kB"
        depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
+       depends on !MIPS_VA_BITS_48
        help
         This option select the standard 4kB Linux page size.  On some
         R3000-family processors this is the only available page size.  Using
@@ -2056,6 +2108,7 @@ config PAGE_SIZE_4KB
 config PAGE_SIZE_8KB
        bool "8kB"
        depends on CPU_R8000 || CPU_CAVIUM_OCTEON
+       depends on !MIPS_VA_BITS_48
        help
          Using 8kB page size will result in higher performance kernel at
          the price of higher memory consumption.  This option is available
@@ -2074,6 +2127,7 @@ config PAGE_SIZE_16KB
 config PAGE_SIZE_32KB
        bool "32kB"
        depends on CPU_CAVIUM_OCTEON
+       depends on !MIPS_VA_BITS_48
        help
          Using 32kB page size will result in higher performance kernel at
          the price of higher memory consumption.  This option is available
@@ -2278,7 +2332,7 @@ config MIPS_CMP
 
 config MIPS_CPS
        bool "MIPS Coherent Processing System support"
-       depends on SYS_SUPPORTS_MIPS_CPS && !CPU_MIPSR6
+       depends on SYS_SUPPORTS_MIPS_CPS
        select MIPS_CM
        select MIPS_CPC
        select MIPS_CPS_PM if HOTPLUG_CPU
@@ -2369,6 +2423,9 @@ config CPU_HAS_WB
 config XKS01
        bool
 
+config CPU_HAS_RIXI
+       bool
+
 #
 # Vectored interrupt mode is an R2 feature
 #
@@ -2399,6 +2456,21 @@ config CPU_R4000_WORKAROUNDS
 config CPU_R4400_WORKAROUNDS
        bool
 
+config MIPS_ASID_SHIFT
+       int
+       default 6 if CPU_R3000 || CPU_TX39XX
+       default 4 if CPU_R8000
+       default 0
+
+config MIPS_ASID_BITS
+       int
+       default 0 if MIPS_ASID_BITS_VARIABLE
+       default 6 if CPU_R3000 || CPU_TX39XX
+       default 8
+
+config MIPS_ASID_BITS_VARIABLE
+       bool
+
 #
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
@@ -2468,6 +2540,61 @@ config NUMA
 config SYS_SUPPORTS_NUMA
        bool
 
+config RELOCATABLE
+       bool "Relocatable kernel"
+       depends on SYS_SUPPORTS_RELOCATABLE && (CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_MIPS32_R6 || CPU_MIPS64_R6)
+       help
+         This builds a kernel image that retains relocation information
+         so it can be loaded someplace besides the default 1MB.
+         The relocations make the kernel binary about 15% larger,
+         but are discarded at runtime
+
+config RELOCATION_TABLE_SIZE
+       hex "Relocation table size"
+       depends on RELOCATABLE
+       range 0x0 0x01000000
+       default "0x00100000"
+       ---help---
+         A table of relocation data will be appended to the kernel binary
+         and parsed at boot to fix up the relocated kernel.
+
+         This option allows the amount of space reserved for the table to be
+         adjusted, although the default of 1Mb should be ok in most cases.
+
+         The build will fail and a valid size suggested if this is too small.
+
+         If unsure, leave at the default value.
+
+config RANDOMIZE_BASE
+       bool "Randomize the address of the kernel image"
+       depends on RELOCATABLE
+       ---help---
+          Randomizes the physical and virtual address at which the
+          kernel image is loaded, as a security feature that
+          deters exploit attempts relying on knowledge of the location
+          of kernel internals.
+
+          Entropy is generated using any coprocessor 0 registers available.
+
+          The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET.
+
+          If unsure, say N.
+
+config RANDOMIZE_BASE_MAX_OFFSET
+       hex "Maximum kASLR offset" if EXPERT
+       depends on RANDOMIZE_BASE
+       range 0x0 0x40000000 if EVA || 64BIT
+       range 0x0 0x08000000
+       default "0x01000000"
+       ---help---
+         When kASLR is active, this provides the maximum offset that will
+         be applied to the kernel image. It should be set according to the
+         amount of physical RAM available in the target system minus
+         PHYSICAL_START and must be a power of 2.
+
+         This is limited by the size of KSEG0, 256Mb on 32-bit or 1Gb with
+         EVA or 64-bit. The default is 16Mb.
+
 config NODES_SHIFT
        int
        default "6"
@@ -2475,7 +2602,7 @@ config NODES_SHIFT
 
 config HW_PERF_EVENTS
        bool "Enable hardware performance counter support for perf events"
-       depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3)
+       depends on PERF_EVENTS && !OPROFILE && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3)
        default y
        help
          Enable hardware performance counter support for perf events. If
@@ -2808,6 +2935,10 @@ choice
 
        config MIPS_CMDLINE_FROM_BOOTLOADER
                bool "Bootloader kernel arguments if available"
+
+       config MIPS_CMDLINE_BUILTIN_EXTEND
+               depends on CMDLINE_BOOL
+               bool "Extend builtin kernel arguments with bootloader arguments"
 endchoice
 
 endmenu
index e78d60dbdffdad93994421e684a87e2f34f8b802..efd7a9dc93c4161a381081c569a5b4e91b182f5e 100644 (file)
@@ -12,6 +12,9 @@
 # for "archclean" cleaning up for this architecture.
 #
 
+archscripts: scripts_basic
+       $(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs
+
 KBUILD_DEFCONFIG := ip22_defconfig
 
 #
@@ -93,6 +96,10 @@ LDFLAGS_vmlinux                      += -G 0 -static -n -nostdlib
 KBUILD_AFLAGS_MODULE           += -mlong-calls
 KBUILD_CFLAGS_MODULE           += -mlong-calls
 
+ifeq ($(CONFIG_RELOCATABLE),y)
+LDFLAGS_vmlinux                        += --emit-relocs
+endif
+
 #
 # pass -msoft-float to GAS if it supports it.  However on newer binutils
 # (specifically newer than 2.24.51.20140728) we then also need to explicitly
@@ -193,6 +200,8 @@ ifeq ($(CONFIG_CPU_HAS_MSA),y)
 toolchain-msa                          := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(comma)-mmsa)
 cflags-$(toolchain-msa)                        += -DTOOLCHAIN_SUPPORTS_MSA
 endif
+toolchain-virt                         := $(call cc-option-yn,$(mips-cflags) -mvirt)
+cflags-$(toolchain-virt)               += -DTOOLCHAIN_SUPPORTS_VIRT
 
 cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER)   += -mcompact-branches=never
 cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal
@@ -310,6 +319,10 @@ rom.bin rom.sw: vmlinux
                $(bootvars-y) $@
 endif
 
+CMD_RELOCS = arch/mips/boot/tools/relocs
+quiet_cmd_relocs = RELOCS  $<
+      cmd_relocs = $(CMD_RELOCS) $<
+
 #
 # Some machines like the Indy need 32-bit ELF binaries for booting purposes.
 # Other need ECOFF, so we build a 32-bit ELF binary for them which we then
@@ -318,6 +331,11 @@ endif
 quiet_cmd_32 = OBJCOPY $@
        cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
 vmlinux.32: vmlinux
+ifeq ($(CONFIG_RELOCATABLE)$(CONFIG_64BIT),yy)
+# Currently, objcopy fails to handle the relocations in the elf64
+# So the relocs tool must be run here to remove them first
+       $(call cmd,relocs)
+endif
        $(call cmd,32)
 
 #
@@ -333,6 +351,9 @@ all:        $(all-y)
 
 # boot
 $(boot-y): $(vmlinux-32) FORCE
+ifeq ($(CONFIG_RELOCATABLE)$(CONFIG_32BIT),yy)
+       $(call cmd,relocs)
+endif
        $(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \
                $(bootvars-y) arch/mips/boot/$@
 
@@ -385,6 +406,7 @@ endif
 archclean:
        $(Q)$(MAKE) $(clean)=arch/mips/boot
        $(Q)$(MAKE) $(clean)=arch/mips/boot/compressed
+       $(Q)$(MAKE) $(clean)=arch/mips/boot/tools
        $(Q)$(MAKE) $(clean)=arch/mips/lasat
 
 define archhelp
index bd34f4093cd9f7d565be85dd3950849ebaa264a0..7ba7ea0a22f80f033242cdee3b9a7da3abc55d03 100644 (file)
@@ -1043,8 +1043,7 @@ static int __init alchemy_clk_init(void)
 
        /* Root of the Alchemy clock tree: external 12MHz crystal osc */
        c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
-                                          CLK_IS_ROOT,
-                                          ALCHEMY_ROOTCLK_RATE);
+                                          0, ALCHEMY_ROOTCLK_RATE);
        ERRCK(c)
 
        /* CPU core clock */
index 13c04cf54afac93bd2c0d8fdaa852ecd9911055e..dfc60209dc63ca231a687175a9e9545c1cd9833a 100644 (file)
@@ -71,18 +71,6 @@ config ATH79_MACH_UBNT_XM
          Say 'Y' here if you want your kernel to support the
          Ubiquiti Networks XM (rev 1.0) board.
 
-choice
-       prompt "Build a DTB in the kernel"
-       optional
-       help
-         Select a devicetree that should be built into the kernel.
-
-       config DTB_TL_WR1043ND_V1
-               bool "TL-WR1043ND Version 1"
-               select BUILTIN_DTB
-               select SOC_AR913X
-endchoice
-
 endmenu
 
 config SOC_AR71XX
index 618dfd735eede5e771061d6a42943150d19b93a6..2e7378467c5cb113e77068625fcca20d0a9b89b9 100644 (file)
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/ath79-clk.h>
 
 #include <asm/div64.h>
 
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
+#include "machtypes.h"
 
 #define AR71XX_BASE_FREQ       40000000
 #define AR724X_BASE_FREQ       40000000
 
-static struct clk *clks[3];
+static struct clk *clks[ATH79_CLK_END];
 static struct clk_onecell_data clk_data = {
        .clks = clks,
        .clk_num = ARRAY_SIZE(clks),
@@ -40,7 +44,7 @@ static struct clk *__init ath79_add_sys_clkdev(
        struct clk *clk;
        int err;
 
-       clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate);
+       clk = clk_register_fixed_rate(NULL, id, NULL, 0, rate);
        if (!clk)
                panic("failed to allocate %s clock structure", id);
 
@@ -78,107 +82,139 @@ static void __init ar71xx_clocks_init(void)
        ahb_rate = cpu_rate / div;
 
        ath79_add_sys_clkdev("ref", ref_rate);
-       clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-       clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-       clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+       clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+       clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+       clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
 
        clk_add_alias("wdt", NULL, "ahb", NULL);
        clk_add_alias("uart", NULL, "ahb", NULL);
 }
 
-static void __init ar724x_clocks_init(void)
+static struct clk * __init ath79_reg_ffclk(const char *name,
+               const char *parent_name, unsigned int mult, unsigned int div)
 {
-       unsigned long ref_rate;
-       unsigned long cpu_rate;
-       unsigned long ddr_rate;
-       unsigned long ahb_rate;
-       u32 pll;
-       u32 freq;
-       u32 div;
+       struct clk *clk;
 
-       ref_rate = AR724X_BASE_FREQ;
-       pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
+       clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div);
+       if (!clk)
+               panic("failed to allocate %s clock structure", name);
 
-       div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK);
-       freq = div * ref_rate;
+       return clk;
+}
 
+static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base)
+{
+       u32 pll;
+       u32 mult, div, ddr_div, ahb_div;
+
+       pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG);
+
+       mult = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK);
        div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2;
-       freq /= div;
 
-       cpu_rate = freq;
+       ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
+       ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
 
-       div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
-       ddr_rate = freq / div;
+       clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", mult, div);
+       clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", mult, div * ddr_div);
+       clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", mult, div * ahb_div);
+}
 
-       div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
-       ahb_rate = cpu_rate / div;
+static void __init ar724x_clocks_init(void)
+{
+       struct clk *ref_clk;
 
-       ath79_add_sys_clkdev("ref", ref_rate);
-       clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-       clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-       clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+       ref_clk = ath79_add_sys_clkdev("ref", AR724X_BASE_FREQ);
+
+       ar724x_clk_init(ref_clk, ath79_pll_base);
+
+       /* just make happy plat_time_init() from arch/mips/ath79/setup.c */
+       clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL);
+       clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL);
+       clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL);
 
        clk_add_alias("wdt", NULL, "ahb", NULL);
        clk_add_alias("uart", NULL, "ahb", NULL);
 }
 
-static void __init ar933x_clocks_init(void)
+static void __init ar9330_clk_init(struct clk *ref_clk, void __iomem *pll_base)
 {
-       unsigned long ref_rate;
-       unsigned long cpu_rate;
-       unsigned long ddr_rate;
-       unsigned long ahb_rate;
        u32 clock_ctrl;
-       u32 cpu_config;
-       u32 freq;
-       u32 t;
+       u32 ref_div;
+       u32 ninit_mul;
+       u32 out_div;
 
-       t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
-       if (t & AR933X_BOOTSTRAP_REF_CLK_40)
-               ref_rate = (40 * 1000 * 1000);
-       else
-               ref_rate = (25 * 1000 * 1000);
+       u32 cpu_div;
+       u32 ddr_div;
+       u32 ahb_div;
 
-       clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG);
+       clock_ctrl = __raw_readl(pll_base + AR933X_PLL_CLOCK_CTRL_REG);
        if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) {
-               cpu_rate = ref_rate;
-               ahb_rate = ref_rate;
-               ddr_rate = ref_rate;
+               ref_div = 1;
+               ninit_mul = 1;
+               out_div = 1;
+
+               cpu_div = 1;
+               ddr_div = 1;
+               ahb_div = 1;
        } else {
-               cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG);
+               u32 cpu_config;
+               u32 t;
+
+               cpu_config = __raw_readl(pll_base + AR933X_PLL_CPU_CONFIG_REG);
 
                t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
                    AR933X_PLL_CPU_CONFIG_REFDIV_MASK;
-               freq = ref_rate / t;
+               ref_div = t;
 
-               t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) &
+               ninit_mul = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) &
                    AR933X_PLL_CPU_CONFIG_NINT_MASK;
-               freq *= t;
 
                t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
                    AR933X_PLL_CPU_CONFIG_OUTDIV_MASK;
                if (t == 0)
                        t = 1;
 
-               freq >>= t;
+               out_div = (1 << t);
 
-               t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) &
+               cpu_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) &
                     AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1;
-               cpu_rate = freq / t;
 
-               t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) &
+               ddr_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) &
                      AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1;
-               ddr_rate = freq / t;
 
-               t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) &
+               ahb_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) &
                     AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1;
-               ahb_rate = freq / t;
        }
 
-       ath79_add_sys_clkdev("ref", ref_rate);
-       clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-       clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-       clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+       clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref",
+                                       ninit_mul, ref_div * out_div * cpu_div);
+       clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref",
+                                       ninit_mul, ref_div * out_div * ddr_div);
+       clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref",
+                                       ninit_mul, ref_div * out_div * ahb_div);
+}
+
+static void __init ar933x_clocks_init(void)
+{
+       struct clk *ref_clk;
+       unsigned long ref_rate;
+       u32 t;
+
+       t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
+       if (t & AR933X_BOOTSTRAP_REF_CLK_40)
+               ref_rate = (40 * 1000 * 1000);
+       else
+               ref_rate = (25 * 1000 * 1000);
+
+       ref_clk = ath79_add_sys_clkdev("ref", ref_rate);
+
+       ar9330_clk_init(ref_clk, ath79_pll_base);
+
+       /* just make happy plat_time_init() from arch/mips/ath79/setup.c */
+       clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL);
+       clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL);
+       clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL);
 
        clk_add_alias("wdt", NULL, "ahb", NULL);
        clk_add_alias("uart", NULL, "ref", NULL);
@@ -310,9 +346,9 @@ static void __init ar934x_clocks_init(void)
                ahb_rate = cpu_pll / (postdiv + 1);
 
        ath79_add_sys_clkdev("ref", ref_rate);
-       clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-       clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-       clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+       clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+       clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+       clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
 
        clk_add_alias("wdt", NULL, "ref", NULL);
        clk_add_alias("uart", NULL, "ref", NULL);
@@ -397,9 +433,9 @@ static void __init qca955x_clocks_init(void)
                ahb_rate = cpu_pll / (postdiv + 1);
 
        ath79_add_sys_clkdev("ref", ref_rate);
-       clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-       clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-       clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+       clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+       clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+       clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
 
        clk_add_alias("wdt", NULL, "ref", NULL);
        clk_add_alias("uart", NULL, "ref", NULL);
@@ -419,8 +455,6 @@ void __init ath79_clocks_init(void)
                qca955x_clocks_init();
        else
                BUG();
-
-       of_clk_init(NULL);
 }
 
 unsigned long __init
@@ -447,8 +481,49 @@ static void __init ath79_clocks_init_dt(struct device_node *np)
 
 CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt);
 CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt);
-CLK_OF_DECLARE(ar9130, "qca,ar9130-pll", ath79_clocks_init_dt);
-CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt);
 CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt);
 CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt);
+
+static void __init ath79_clocks_init_dt_ng(struct device_node *np)
+{
+       struct clk *ref_clk;
+       void __iomem *pll_base;
+       const char *dnfn = of_node_full_name(np);
+
+       ref_clk = of_clk_get(np, 0);
+       if (IS_ERR(ref_clk)) {
+               pr_err("%s: of_clk_get failed\n", dnfn);
+               goto err;
+       }
+
+       pll_base = of_iomap(np, 0);
+       if (!pll_base) {
+               pr_err("%s: can't map pll registers\n", dnfn);
+               goto err_clk;
+       }
+
+       if (of_device_is_compatible(np, "qca,ar9130-pll"))
+               ar724x_clk_init(ref_clk, pll_base);
+       else if (of_device_is_compatible(np, "qca,ar9330-pll"))
+               ar9330_clk_init(ref_clk, pll_base);
+       else {
+               pr_err("%s: could not find any appropriate clk_init()\n", dnfn);
+               goto err_clk;
+       }
+
+       if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) {
+               pr_err("%s: could not register clk provider\n", dnfn);
+               goto err_clk;
+       }
+
+       return;
+
+err_clk:
+       clk_put(ref_clk);
+
+err:
+       return;
+}
+CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng);
+CLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt_ng);
 #endif
index 3cedd1f95e0f0897cf3c1d47b6c27cb9182c4003..d071a3a0f87698ffb6384c6fa4dfa5d7bda5da40 100644 (file)
@@ -46,12 +46,12 @@ void ath79_ddr_ctrl_init(void)
 {
        ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
                                         AR71XX_DDR_CTRL_SIZE);
-       if (soc_is_ar71xx() || soc_is_ar934x()) {
-               ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c;
-               ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c;
-       } else {
+       if (soc_is_ar913x() || soc_is_ar724x() || soc_is_ar933x()) {
                ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c;
                ath79_ddr_pci_win_base = 0;
+       } else {
+               ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c;
+               ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c;
        }
 }
 EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init);
@@ -76,14 +76,14 @@ void ath79_ddr_set_pci_windows(void)
 {
        BUG_ON(!ath79_ddr_pci_win_base);
 
-       __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0);
-       __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1);
-       __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2);
-       __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3);
-       __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4);
-       __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5);
-       __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6);
-       __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7);
+       __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0);
+       __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4);
+       __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8);
+       __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc);
+       __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10);
+       __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14);
+       __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18);
+       __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c);
 }
 EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows);
 
index be451ee4a5eaf5b8ba6de0d11fc8c76f6d6db7fa..7adab180e0ca61e32f6e4e811d09f041ddd1a4ee 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/bootmem.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 
@@ -203,26 +204,57 @@ void __init plat_mem_setup(void)
        fdt_start = fw_getenvl("fdt_start");
        if (fdt_start)
                __dt_setup_arch((void *)KSEG0ADDR(fdt_start));
-#ifdef CONFIG_BUILTIN_DTB
-       else
-               __dt_setup_arch(__dtb_start);
-#endif
+       else if (fw_arg0 == -2)
+               __dt_setup_arch((void *)KSEG0ADDR(fw_arg1));
 
-       ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
-                                          AR71XX_RESET_SIZE);
-       ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
-                                        AR71XX_PLL_SIZE);
-       ath79_detect_sys_type();
-       ath79_ddr_ctrl_init();
+       if (mips_machtype != ATH79_MACH_GENERIC_OF) {
+               ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
+                                                  AR71XX_RESET_SIZE);
+               ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
+                                                AR71XX_PLL_SIZE);
+               ath79_detect_sys_type();
+               ath79_ddr_ctrl_init();
 
-       if (mips_machtype != ATH79_MACH_GENERIC_OF)
                detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
 
-       _machine_restart = ath79_restart;
+               /* OF machines should use the reset driver */
+               _machine_restart = ath79_restart;
+       }
+
        _machine_halt = ath79_halt;
        pm_power_off = ath79_halt;
 }
 
+static void __init ath79_of_plat_time_init(void)
+{
+       struct device_node *np;
+       struct clk *clk;
+       unsigned long cpu_clk_rate;
+
+       of_clk_init(NULL);
+
+       np = of_get_cpu_node(0, NULL);
+       if (!np) {
+               pr_err("Failed to get CPU node\n");
+               return;
+       }
+
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk)) {
+               pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
+               return;
+       }
+
+       cpu_clk_rate = clk_get_rate(clk);
+
+       pr_info("CPU clock: %lu.%03lu MHz\n",
+               cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000);
+
+       mips_hpt_frequency = cpu_clk_rate / 2;
+
+       clk_put(clk);
+}
+
 void __init plat_time_init(void)
 {
        unsigned long cpu_clk_rate;
@@ -230,6 +262,11 @@ void __init plat_time_init(void)
        unsigned long ddr_clk_rate;
        unsigned long ref_clk_rate;
 
+       if (IS_ENABLED(CONFIG_OF) && mips_machtype == ATH79_MACH_GENERIC_OF) {
+               ath79_of_plat_time_init();
+               return;
+       }
+
        ath79_clocks_init();
 
        cpu_clk_rate = ath79_get_sys_clk_rate("cpu");
index 66bea4ecf449eb497b9bb11c591df18cfe4babb0..6d8615074075cd3f9983ec0d1755c4cfe6283955 100644 (file)
@@ -3,5 +3,5 @@
 # under Linux.
 #
 
-obj-y                          += irq.o prom.o serial.o setup.o time.o sprom.o
+obj-y                          += irq.o prom.o serial.o setup.o time.o
 obj-y                          += board.o buttons.o leds.o workarounds.o
index 41796befa9df53b1fc35b20bfeaec17a5db68136..0367ac7286fe34998d558d426680e0347a49765d 100644 (file)
@@ -10,9 +10,6 @@
 /* prom.c */
 void __init bcm47xx_prom_highmem_init(void);
 
-/* sprom.c */
-void bcm47xx_sprom_register_fallbacks(void);
-
 /* buttons.c */
 int __init bcm47xx_buttons_register(void);
 
index c807e32d6d81c3c880bd375738e78fe0c87d0f07..6054d49e608eec038e1bbd49599bc783270aa09a 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "bcm47xx_private.h"
 
+#include <linux/bcm47xx_sprom.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/ethtool.h>
@@ -151,7 +152,6 @@ void __init plat_mem_setup(void)
                pr_info("Using bcma bus\n");
 #ifdef CONFIG_BCM47XX_BCMA
                bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
-               bcm47xx_sprom_register_fallbacks();
                bcm47xx_register_bcma();
                bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
 #ifdef CONFIG_HIGHMEM
index e2c4fd682c740822eb2bcf1a2101a7e1fa47dc61..264328d528c72e40ad12c6b8bbff2bbb9ccda742 100644 (file)
@@ -21,6 +21,10 @@ config DT_BCM93384WVG_VIPER
        bool "BCM93384WVG Viper CPU (EXPERIMENTAL)"
        select BUILTIN_DTB
 
+config DT_BCM96358NB4SER
+       bool "BCM96358NB4SER"
+       select BUILTIN_DTB
+
 config DT_BCM96368MVWG
        bool "BCM96368MVWG"
        select BUILTIN_DTB
index 35535284b39efb323cb63b4f8ec37dcdfbdb7f60..f146d1219bde86b71c5e69d037c51d4d27d74651 100644 (file)
@@ -95,6 +95,15 @@ static void bcm6328_quirks(void)
                bcm63xx_fixup_cpu1();
 }
 
+static void bcm6358_quirks(void)
+{
+       /*
+        * BCM6358 needs special handling for its shared TLB, so
+        * disable SMP for now
+        */
+       bmips_smp_enabled = 0;
+}
+
 static void bcm6368_quirks(void)
 {
        bcm63xx_fixup_cpu1();
@@ -104,13 +113,16 @@ static const struct bmips_quirk bmips_quirk_list[] = {
        { "brcm,bcm3384-viper",         &bcm3384_viper_quirks           },
        { "brcm,bcm33843-viper",        &bcm3384_viper_quirks           },
        { "brcm,bcm6328",               &bcm6328_quirks                 },
+       { "brcm,bcm6358",               &bcm6358_quirks                 },
        { "brcm,bcm6368",               &bcm6368_quirks                 },
        { "brcm,bcm63168",              &bcm6368_quirks                 },
+       { "brcm,bcm63268",              &bcm6368_quirks                 },
        { },
 };
 
 void __init prom_init(void)
 {
+       bmips_cpu_setup();
        register_bmips_smp_ops();
 }
 
index 309d2ad67e4d6ee3d7c8c844506b5ae8bd92b24d..90aca95fe3149696d772e3ae41cdcfa388d79b80 100644 (file)
@@ -37,8 +37,13 @@ vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT)               += $(obj)/dbg.o
 vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
 vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM) += $(obj)/uart-prom.o
 vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY)                += $(obj)/uart-alchemy.o
+vmlinuzobjs-$(CONFIG_ATH79)                       += $(obj)/uart-ath79.o
 endif
 
+extra-y += uart-ath79.c
+$(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c
+       $(call cmd,shipped)
+
 vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o $(obj)/bswapsi.o
 
 extra-y += ashldi3.c bswapsi.c
index eabeb603e805d72c0869867594fbea49dd26189c..fda9d387cc08640067ef93650aa01e78d4536007 100644 (file)
@@ -1,5 +1,6 @@
 dtb-$(CONFIG_DT_BCM93384WVG)           += bcm93384wvg.dtb
 dtb-$(CONFIG_DT_BCM93384WVG_VIPER)     += bcm93384wvg_viper.dtb
+dtb-$(CONFIG_DT_BCM96358NB4SER)                += bcm96358nb4ser.dtb
 dtb-$(CONFIG_DT_BCM96368MVWG)          += bcm96368mvwg.dtb
 dtb-$(CONFIG_DT_BCM9EJTAGPRB)          += bcm9ejtagprb.dtb
 dtb-$(CONFIG_DT_BCM97125CBMB)          += bcm97125cbmb.dtb
@@ -14,6 +15,7 @@ dtb-$(CONFIG_DT_BCM97435SVMB)         += bcm97435svmb.dtb
 dtb-$(CONFIG_DT_NONE)                  += \
                                                bcm93384wvg.dtb         \
                                                bcm93384wvg_viper.dtb   \
+                                               bcm96358nb4ser.dtb      \
                                                bcm96368mvwg.dtb        \
                                                bcm9ejtagprb.dtb        \
                                                bcm97125cbmb.dtb        \
index 9d19236f53e7b9a33c2a2cc2ccfd593322b04074..5633b9d90f5549bceac0c8a8f468ac8bffdd5243 100644 (file)
@@ -23,7 +23,7 @@
        };
 
        clocks {
-               periph_clk: periph_clk {
+               periph_clk: periph-clk {
                        compatible = "fixed-clock";
                        #clock-cells = <0>;
                        clock-frequency = <50000000>;
        };
 
        aliases {
-               leds0 = &leds0;
-               uart0 = &uart0;
+               serial0 = &uart0;
+               serial1 = &uart1;
        };
 
-       cpu_intc: cpu_intc {
+       cpu_intc: interrupt-controller {
                #address-cells = <0>;
                compatible = "mti,cpu-interrupt-controller";
 
                compatible = "simple-bus";
                ranges;
 
-               periph_intc: periph_intc@10000020 {
-                       compatible = "brcm,bcm3380-l2-intc";
-                       reg = <0x10000024 0x4 0x1000002c 0x4>,
-                             <0x10000020 0x4 0x10000028 0x4>;
+               periph_intc: interrupt-controller@10000020 {
+                       compatible = "brcm,bcm6345-l1-intc";
+                       reg = <0x10000020 0x10>,
+                             <0x10000030 0x10>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&cpu_intc>;
-                       interrupts = <2>;
+                       interrupts = <2>, <3>;
                };
 
                uart0: serial@10000100 {
                        status = "disabled";
                };
 
-               timer: timer@10000040 {
+               uart1: serial@10000120 {
+                       compatible = "brcm,bcm6345-uart";
+                       reg = <0x10000120 0x18>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <39>;
+                       clocks = <&periph_clk>;
+                       status = "disabled";
+               };
+
+               timer: syscon@10000040 {
                        compatible = "syscon";
                        reg = <0x10000040 0x2c>;
                        native-endian;
                };
 
-               reboot {
+               reboot: syscon-reboot@10000068 {
                        compatible = "syscon-reboot";
                        regmap = <&timer>;
                        offset = <0x28>;
                        reg = <0x10000800 0x24>;
                        status = "disabled";
                };
+
+               ehci: usb@10002500 {
+                       compatible = "brcm,bcm6328-ehci", "generic-ehci";
+                       reg = <0x10002500 0x100>;
+                       big-endian;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <42>;
+                       status = "disabled";
+               };
+
+               ohci: usb@10002600 {
+                       compatible = "brcm,bcm6328-ohci", "generic-ohci";
+                       reg = <0x10002600 0x100>;
+                       big-endian;
+                       no-big-frame-no;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <41>;
+                       status = "disabled";
+               };
        };
 };
diff --git a/arch/mips/boot/dts/brcm/bcm6358.dtsi b/arch/mips/boot/dts/brcm/bcm6358.dtsi
new file mode 100644 (file)
index 0000000..f9d8d39
--- /dev/null
@@ -0,0 +1,130 @@
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "brcm,bcm6358";
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               mips-hpt-frequency = <150000000>;
+
+               cpu@0 {
+                       compatible = "brcm,bmips4350";
+                       device_type = "cpu";
+                       reg = <0>;
+               };
+
+               cpu@1 {
+                       compatible = "brcm,bmips4350";
+                       device_type = "cpu";
+                       reg = <1>;
+               };
+       };
+
+       clocks {
+               periph_clk: periph-clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <50000000>;
+               };
+       };
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+       };
+
+       cpu_intc: interrupt-controller {
+               #address-cells = <0>;
+               compatible = "mti,cpu-interrupt-controller";
+
+               interrupt-controller;
+               #interrupt-cells = <1>;
+       };
+
+       ubus {
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               compatible = "simple-bus";
+               ranges;
+
+               periph_cntl: syscon@fffe0000 {
+                       compatible = "syscon";
+                       reg = <0xfffe0000 0xc>;
+                       native-endian;
+               };
+
+               reboot: syscon-reboot@fffe0008 {
+                       compatible = "syscon-reboot";
+                       regmap = <&periph_cntl>;
+                       offset = <0x8>;
+                       mask = <0x1>;
+               };
+
+               periph_intc: interrupt-controller@fffe000c {
+                       compatible = "brcm,bcm6345-l1-intc";
+                       reg = <0xfffe000c 0x8>,
+                             <0xfffe0038 0x8>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&cpu_intc>;
+                       interrupts = <2>, <3>;
+               };
+
+               leds0: led-controller@fffe00d0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "brcm,bcm6358-leds";
+                       reg = <0xfffe00d0 0x8>;
+
+                       status = "disabled";
+               };
+
+               uart0: serial@fffe0100 {
+                       compatible = "brcm,bcm6345-uart";
+                       reg = <0xfffe0100 0x18>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <2>;
+
+                       clocks = <&periph_clk>;
+
+                       status = "disabled";
+               };
+
+               uart1: serial@fffe0120 {
+                       compatible = "brcm,bcm6345-uart";
+                       reg = <0xfffe0120 0x18>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <3>;
+
+                       clocks = <&periph_clk>;
+
+                       status = "disabled";
+               };
+
+               ehci: usb@fffe1300 {
+                       compatible = "brcm,bcm6358-ehci", "generic-ehci";
+                       reg = <0xfffe1300 0x100>;
+                       big-endian;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <10>;
+                       status = "disabled";
+               };
+
+               ohci: usb@fffe1400 {
+                       compatible = "brcm,bcm6358-ohci", "generic-ohci";
+                       reg = <0xfffe1400 0x100>;
+                       big-endian;
+                       no-big-frame-no;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <5>;
+                       status = "disabled";
+               };
+       };
+};
index 1f6b9b5cddb4c0890b02cb37edb5c0c3331ba8dd..d0e3a70b32e2e65d43e8ab1706a5bcc0579e318e 100644 (file)
                        device_type = "cpu";
                        reg = <1>;
                };
-
        };
 
        clocks {
-               periph_clk: periph_clk {
+               periph_clk: periph-clk {
                        compatible = "fixed-clock";
                        #clock-cells = <0>;
                        clock-frequency = <50000000>;
        };
 
        aliases {
-               leds0 = &leds0;
-               uart0 = &uart0;
+               serial0 = &uart0;
+               serial1 = &uart1;
        };
 
-       cpu_intc: cpu_intc {
+       cpu_intc: interrupt-controller {
                #address-cells = <0>;
                compatible = "mti,cpu-interrupt-controller";
 
                        mask = <0x1>;
                };
 
-               periph_intc: periph_intc@10000020 {
-                       compatible = "brcm,bcm3380-l2-intc";
-                       reg = <0x10000024 0x4 0x1000002c 0x4>,
-                             <0x10000020 0x4 0x10000028 0x4>;
+               periph_intc: interrupt-controller@10000020 {
+                       compatible = "brcm,bcm6345-l1-intc";
+                       reg = <0x10000020 0x10>,
+                             <0x10000030 0x10>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&cpu_intc>;
-                       interrupts = <2>;
+                       interrupts = <2>, <3>;
                };
 
                leds0: led-controller@100000d0 {
                        status = "disabled";
                };
 
-               ehci0: usb@10001500 {
+               uart1: serial@10000120 {
+                       compatible = "brcm,bcm6345-uart";
+                       reg = <0x10000120 0x18>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <3>;
+                       clocks = <&periph_clk>;
+                       status = "disabled";
+               };
+
+               ehci: usb@10001500 {
                        compatible = "brcm,bcm6368-ehci", "generic-ehci";
                        reg = <0x10001500 0x100>;
                        big-endian;
                        status = "disabled";
                };
 
-               ohci0: usb@10001600 {
+               ohci: usb@10001600 {
                        compatible = "brcm,bcm6368-ohci", "generic-ohci";
                        reg = <0x10001600 0x100>;
                        big-endian;
index 3ae16053a0c98763d8b8239eff18630105c2239a..550e1d9e3ee039eb06f14816bde573a03268ef4c 100644 (file)
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406780 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0xf000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <18>;
+                       interrupts = <18>, <19>;
+                       interrupt-names = "upg_main", "upg_bsc";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               uart1: serial@406b40 {
+                       compatible = "ns16550a";
+                       reg = <0x406b40 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       native-endian;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <64>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               uart2: serial@406b80 {
+                       compatible = "ns16550a";
+                       reg = <0x406b80 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       native-endian;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <65>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@406380 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406380 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
                ehci0: usb@488300 {
                        compatible = "brcm,bcm7125-ehci", "generic-ehci";
                        reg = <0x488300 0x100>;
index be7991917d2950f0d48d0c04dfd9b478856fcc35..ec959061d52e30ef96c71fd78bd07f72b63c124e 100644 (file)
@@ -24,8 +24,6 @@
 
        aliases {
                uart0 = &uart0;
-               uart1 = &uart1;
-               uart2 = &uart2;
        };
 
        cpu_intc: cpu_intc {
                        interrupts = <40>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       brcm,broken-ncq;
-                       brcm,broken-phy;
                        status = "disabled";
 
                        sata0: sata-port@0 {
                        };
                };
 
-               sata_phy: sata-phy@1800000 {
+               sata_phy: sata-phy@180100 {
                        compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
                        reg = <0x180100 0x0eff>;
                        reg-names = "phy";
index 060805be619a23ac8812576a59a47fead67c98aa..ca57fb5eb1222e4e42066e4b99d5239a85121791 100644 (file)
@@ -18,8 +18,6 @@
 
        aliases {
                uart0 = &uart0;
-               uart1 = &uart1;
-               uart2 = &uart2;
        };
 
        cpu_intc: cpu_intc {
index bcdb09bfe07ba3ed86369f9938ac50db678d250f..1c0c3d438c7ac42b6df46523077c8804bdaf99b8 100644 (file)
@@ -18,8 +18,6 @@
 
        aliases {
                uart0 = &uart0;
-               uart1 = &uart1;
-               uart2 = &uart2;
        };
 
        cpu_intc: cpu_intc {
                        interrupts = <66>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <86>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@180100 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
index d3b1b762e6c3e21c3e129aea6127f071d4417845..6b4713add4b8a9e176d7556fe2a27360cb7f745d 100644 (file)
@@ -24,8 +24,6 @@
 
        aliases {
                uart0 = &uart0;
-               uart1 = &uart1;
-               uart2 = &uart2;
        };
 
        cpu_intc: cpu_intc {
                        interrupts = <86>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       brcm,broken-ncq;
-                       brcm,broken-phy;
                        status = "disabled";
 
                        sata0: sata-port@0 {
                        };
                };
 
-               sata_phy: sata-phy@1800000 {
+               sata_phy: sata-phy@180100 {
                        compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
                        reg = <0x180100 0x0eff>;
                        reg-names = "phy";
index 3302a1b8a5c9b841b46b931ab501327aa2099b30..0586bf662571e633609517c573e147dddc584c6f 100644 (file)
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406780 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x1f000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <18>;
+                       interrupts = <18>, <19>;
+                       interrupt-names = "upg_main", "upg_bsc";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               uart1: serial@406b40 {
+                       compatible = "ns16550a";
+                       reg = <0x406b40 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <64>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               uart2: serial@406b80 {
+                       compatible = "ns16550a";
+                       reg = <0x406b80 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <65>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@406380 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406380 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
+               bsce: i2c@406800 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406800 0x58>;
+                     interrupts = <28>;
+                     interrupt-names = "upg_bsce";
+                     status = "disabled";
+               };
+
                enet0: ethernet@468000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
index 15b27aae15a9620e439de3e13162e16b2e8306b1..c1c15edaf829ba231eeac9afa77c42876e530593 100644 (file)
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406780 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <55>;
+                       interrupts = <55>, <53>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@409480 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x409480 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x18000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <56>, <54>, <59>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               uart1: serial@406b40 {
+                       compatible = "ns16550a";
+                       reg = <0x406b40 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <62>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               uart2: serial@406b80 {
+                       compatible = "ns16550a";
+                       reg = <0x406b80 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <63>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               bsca: i2c@409180 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x409180 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@409400 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x409400 0x58>;
+                     interrupts = <28>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
+               bsce: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bsce";
+                     status = "disabled";
+               };
+
                enet0: ethernet@b80000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
                        reg-names = "ahci", "top-ctrl";
                        reg = <0x181000 0xa9c>, <0x180020 0x1c>;
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <40>;
+                       interrupts = <41>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       brcm,broken-ncq;
-                       brcm,broken-phy;
                        status = "disabled";
 
                        sata0: sata-port@0 {
                        };
                };
 
-               sata_phy: sata-phy@1800000 {
+               sata_phy: sata-phy@180100 {
                        compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
                        reg = <0x180100 0x0eff>;
                        reg-names = "phy";
index 56035e5b70084918a121247ace50f19d3fefdfe9..a874d3a0e2ee637402e3feef5c5a45a6fca1732f 100644 (file)
@@ -7,7 +7,7 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
-               mips-hpt-frequency = <163125000>;
+               mips-hpt-frequency = <175625000>;
 
                cpu@0 {
                        compatible = "brcm,bmips5200";
 
                periph_intc: periph_intc@41b500 {
                        compatible = "brcm,bcm7038-l1-intc";
-                       reg = <0x41b500 0x40>, <0x41b600 0x40>;
+                       reg = <0x41b500 0x40>, <0x41b600 0x40>,
+                               <0x41b700 0x40>, <0x41b800 0x40>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&cpu_intc>;
-                       interrupts = <2>, <3>;
+                       interrupts = <2>, <3>, <2>, <3>;
                };
 
                sun_l2_intc: sun_l2_intc@403000 {
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406780 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <60>;
+                       interrupts = <60>, <58>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@409480 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x409480 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x18000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <61>, <59>, <64>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               uart1: serial@406b40 {
+                       compatible = "ns16550a";
+                       reg = <0x406b40 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <67>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               uart2: serial@406b80 {
+                       compatible = "ns16550a";
+                       reg = <0x406b80 0x20>;
+                       reg-io-width = <0x4>;
+                       reg-shift = <0x2>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <68>;
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
+
+               bsca: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@409400 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x409400 0x58>;
+                     interrupts = <28>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
+               bsce: i2c@409180 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x409180 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bsce";
+                     status = "disabled";
+               };
+
                enet0: ethernet@b80000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
                        interrupts = <78>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <45>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@180100 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
diff --git a/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts b/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts
new file mode 100644 (file)
index 0000000..f412117
--- /dev/null
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+/include/ "bcm6358.dtsi"
+
+/ {
+       compatible = "sfr,nb4-ser", "brcm,bcm6358";
+       model = "SFR Neufbox 4 (Sercomm)";
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x00000000 0x02000000>;
+       };
+
+       chosen {
+               stdout-path = &uart0;
+       };
+};
+
+&leds0 {
+       status = "ok";
+
+       led@0 {
+               reg = <0>;
+               active-low;
+               label = "nb4-ser:white:alarm";
+       };
+       led@2 {
+               reg = <2>;
+               active-low;
+               label = "nb4-ser:white:tv";
+       };
+       led@3 {
+               reg = <3>;
+               active-low;
+               label = "nb4-ser:white:tel";
+       };
+       led@4 {
+               reg = <4>;
+               active-low;
+               label = "nb4-ser:white:adsl";
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
index 0e890c28fe5ca4c4bba7fc47c708b07e390d24e4..8c71c684573032091f05c66f9c716284993327aa 100644 (file)
 };
 
 /* FIXME: need to set up USB_CTRL registers first */
-&ehci0 {
+&ehci {
        status = "disabled";
 };
 
-&ohci0 {
+&ohci {
        status = "disabled";
 };
index e046b1109eabeeb111a2e9a736af99583ee4ce50..f2449d147c6da9177010d869f90ac0d1ead9e468 100644 (file)
        status = "okay";
 };
 
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
 /* FIXME: USB is wonky; disable it for now */
 &ehci0 {
        status = "disabled";
index d48462e091f176e6be77eeb301f769b40ef1afbc..73124be9548aeff58f1fd507883c3f2637808a55 100644 (file)
 &ohci0 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+};
index 67fe1f3a38918f472a01cdab4a38d90cf31cac71..600d57abee05c1bb8e8f22c57d67f1fb7a509a8c 100644 (file)
        status = "okay";
 };
 
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
+&bsce {
+       status = "okay";
+};
+
 /* FIXME: MAC driver comes up but cannot attach to PHY */
 &enet0 {
        status = "disabled";
index 689c68a4f9c8b821ec2acc8c48e2e386526957dc..119c714805cbc8257f1addc89a9b17289ffa73ec 100644 (file)
        status = "okay";
 };
 
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
+&bsce {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
index 1df08818352362ca5f50cda194271ac97d7ba185..43e3ba27f07ba2ddc6935a7f80ba4a2b238f67ca 100644 (file)
@@ -14,7 +14,7 @@
        };
 
        chosen {
-               bootargs = "console=ttyS0,115200 maxcpus=1";
+               bootargs = "console=ttyS0,115200";
                stdout-path = &uart0;
        };
 };
        status = "okay";
 };
 
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
+&bsce {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
 &ohci3 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+};
diff --git a/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts b/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts
new file mode 100644 (file)
index 0000000..d6bc994
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Device tree source for D-Link DSR-1000N.
+ *
+ * Written by: Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/include/ "octeon_3xxx.dtsi"
+
+/ {
+       model = "dlink,dsr-1000n";
+
+       soc@0 {
+               smi0: mdio@1180000001800 {
+                       phy8: ethernet-phy@8 {
+                               reg = <8>;
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                       };
+               };
+
+               pip: pip@11800a0000000 {
+                       interface@0 {
+                               ethernet@0 {
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                       };
+                               };
+                               ethernet@1 {
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                       };
+                               };
+                               ethernet@2 {
+                                       phy-handle = <&phy8>;
+                               };
+                       };
+               };
+
+               twsi0: i2c@1180000001000 {
+                       rtc@68 {
+                               compatible = "dallas,ds1337";
+                               reg = <0x68>;
+                       };
+               };
+
+               uart0: serial@1180000000800 {
+                       clock-frequency = <500000000>;
+               };
+
+               usbn: usbn@1180068000000 {
+                       refclk-frequency = <12000000>;
+                       refclk-type = "crystal";
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               usb1 {
+                       label = "usb1";
+                       gpios = <&gpio 9 1>; /* Active low */
+               };
+
+               usb2 {
+                       label = "usb2";
+                       gpios = <&gpio 10 1>; /* Active low */
+               };
+       };
+
+       aliases {
+               pip = &pip;
+       };
+};
index 9c48e0586ba770ccb40a0e6e41c3878e8d015dca..de61f02d3ef6105b90d1b790d6ea3b3ccd832da7 100644 (file)
@@ -1,4 +1,3 @@
-/dts-v1/;
 /*
  * OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
  *
@@ -6,56 +5,12 @@
  * use.         Because of this, it contains a super-set of the available
  * devices and properties.
  */
-/ {
-       compatible = "cavium,octeon-3860";
-       #address-cells = <2>;
-       #size-cells = <2>;
-       interrupt-parent = <&ciu>;
-
-       soc@0 {
-               compatible = "simple-bus";
-               #address-cells = <2>;
-               #size-cells = <2>;
-               ranges; /* Direct mapping */
-
-               ciu: interrupt-controller@1070000000000 {
-                       compatible = "cavium,octeon-3860-ciu";
-                       interrupt-controller;
-                       /* Interrupts are specified by two parts:
-                        * 1) Controller register (0 or 1)
-                        * 2) Bit within the register (0..63)
-                        */
-                       #interrupt-cells = <2>;
-                       reg = <0x10700 0x00000000 0x0 0x7000>;
-               };
 
-               gpio: gpio-controller@1070000000800 {
-                       #gpio-cells = <2>;
-                       compatible = "cavium,octeon-3860-gpio";
-                       reg = <0x10700 0x00000800 0x0 0x100>;
-                       gpio-controller;
-                       /* Interrupts are specified by two parts:
-                        * 1) GPIO pin number (0..15)
-                        * 2) Triggering (1 - edge rising
-                        *                2 - edge falling
-                        *                4 - level active high
-                        *                8 - level active low)
-                        */
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-                       /* The GPIO pin connect to 16 consecutive CUI bits */
-                       interrupts = <0 16>, <0 17>, <0 18>, <0 19>,
-                                    <0 20>, <0 21>, <0 22>, <0 23>,
-                                    <0 24>, <0 25>, <0 26>, <0 27>,
-                                    <0 28>, <0 29>, <0 30>, <0 31>;
-               };
+/include/ "octeon_3xxx.dtsi"
 
+/ {
+       soc@0 {
                smi0: mdio@1180000001800 {
-                       compatible = "cavium,octeon-3860-mdio";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x11800 0x00001800 0x0 0x40>;
-
                        phy0: ethernet-phy@0 {
                                compatible = "marvell,88e1118";
                                marvell,reg-init =
                };
 
                pip: pip@11800a0000000 {
-                       compatible = "cavium,octeon-3860-pip";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x11800 0xa0000000 0x0 0x2000>;
-
                        interface@0 {
-                               compatible = "cavium,octeon-3860-pip-interface";
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               reg = <0>; /* interface */
-
                                ethernet@0 {
-                                       compatible = "cavium,octeon-3860-pip-port";
-                                       reg = <0x0>; /* Port */
-                                       local-mac-address = [ 00 00 00 00 00 00 ];
                                        phy-handle = <&phy2>;
                                        cavium,alt-phy-handle = <&phy100>;
                                };
                                ethernet@1 {
-                                       compatible = "cavium,octeon-3860-pip-port";
-                                       reg = <0x1>; /* Port */
-                                       local-mac-address = [ 00 00 00 00 00 00 ];
                                        phy-handle = <&phy3>;
                                        cavium,alt-phy-handle = <&phy101>;
                                };
                                ethernet@2 {
-                                       compatible = "cavium,octeon-3860-pip-port";
-                                       reg = <0x2>; /* Port */
-                                       local-mac-address = [ 00 00 00 00 00 00 ];
                                        phy-handle = <&phy4>;
                                        cavium,alt-phy-handle = <&phy102>;
                                };
                        };
 
                        interface@1 {
-                               compatible = "cavium,octeon-3860-pip-interface";
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               reg = <1>; /* interface */
-
                                ethernet@0 {
                                        compatible = "cavium,octeon-3860-pip-port";
                                        reg = <0x0>; /* Port */
                };
 
                twsi0: i2c@1180000001000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "cavium,octeon-3860-twsi";
-                       reg = <0x11800 0x00001000 0x0 0x200>;
-                       interrupts = <0 45>;
-                       clock-frequency = <100000>;
-
                        rtc@68 {
                                compatible = "dallas,ds1337";
                                reg = <0x68>;
                        clock-frequency = <100000>;
                };
 
-               uart0: serial@1180000000800 {
-                       compatible = "cavium,octeon-3860-uart","ns16550";
-                       reg = <0x11800 0x00000800 0x0 0x400>;
-                       clock-frequency = <0>;
-                       current-speed = <115200>;
-                       reg-shift = <3>;
-                       interrupts = <0 34>;
-               };
-
                uart1: serial@1180000000c00 {
                        compatible = "cavium,octeon-3860-uart","ns16550";
                        reg = <0x11800 0x00000c00 0x0 0x400>;
                };
 
                bootbus: bootbus@1180000000000 {
-                       compatible = "cavium,octeon-3860-bootbus";
-                       reg = <0x11800 0x00000000 0x0 0x200>;
-                       /* The chip select number and offset */
-                       #address-cells = <2>;
-                       /* The size of the chip select region */
-                       #size-cells = <1>;
-                       ranges = <0 0  0x0 0x1f400000  0xc00000>,
-                                <1 0  0x10000 0x30000000  0>,
-                                <2 0  0x10000 0x40000000  0>,
-                                <3 0  0x10000 0x50000000  0>,
-                                <4 0  0x0 0x1d020000  0x10000>,
-                                <5 0  0x0 0x1d040000  0x10000>,
-                                <6 0  0x0 0x1d050000  0x10000>,
-                                <7 0  0x10000 0x90000000  0>;
-
-                       cavium,cs-config@0 {
-                               compatible = "cavium,octeon-3860-bootbus-config";
-                               cavium,cs-index = <0>;
-                               cavium,t-adr  = <20>;
-                               cavium,t-ce   = <60>;
-                               cavium,t-oe   = <60>;
-                               cavium,t-we   = <45>;
-                               cavium,t-rd-hld = <35>;
-                               cavium,t-wr-hld = <45>;
-                               cavium,t-pause  = <0>;
-                               cavium,t-wait   = <0>;
-                               cavium,t-page   = <35>;
-                               cavium,t-rd-dly = <0>;
-
-                               cavium,pages     = <0>;
-                               cavium,bus-width = <8>;
-                       };
-                       cavium,cs-config@4 {
-                               compatible = "cavium,octeon-3860-bootbus-config";
-                               cavium,cs-index = <4>;
-                               cavium,t-adr  = <320>;
-                               cavium,t-ce   = <320>;
-                               cavium,t-oe   = <320>;
-                               cavium,t-we   = <320>;
-                               cavium,t-rd-hld = <320>;
-                               cavium,t-wr-hld = <320>;
-                               cavium,t-pause  = <320>;
-                               cavium,t-wait   = <320>;
-                               cavium,t-page   = <320>;
-                               cavium,t-rd-dly = <0>;
-
-                               cavium,pages     = <0>;
-                               cavium,bus-width = <8>;
-                       };
-                       cavium,cs-config@5 {
-                               compatible = "cavium,octeon-3860-bootbus-config";
-                               cavium,cs-index = <5>;
-                               cavium,t-adr  = <5>;
-                               cavium,t-ce   = <300>;
-                               cavium,t-oe   = <125>;
-                               cavium,t-we   = <150>;
-                               cavium,t-rd-hld = <100>;
-                               cavium,t-wr-hld = <30>;
-                               cavium,t-pause  = <0>;
-                               cavium,t-wait   = <30>;
-                               cavium,t-page   = <320>;
-                               cavium,t-rd-dly = <0>;
-
-                               cavium,pages     = <0>;
-                               cavium,bus-width = <16>;
-                       };
-                       cavium,cs-config@6 {
-                               compatible = "cavium,octeon-3860-bootbus-config";
-                               cavium,cs-index = <6>;
-                               cavium,t-adr  = <5>;
-                               cavium,t-ce   = <300>;
-                               cavium,t-oe   = <270>;
-                               cavium,t-we   = <150>;
-                               cavium,t-rd-hld = <100>;
-                               cavium,t-wr-hld = <70>;
-                               cavium,t-pause  = <0>;
-                               cavium,t-wait   = <0>;
-                               cavium,t-page   = <320>;
-                               cavium,t-rd-dly = <0>;
-
-                               cavium,pages     = <0>;
-                               cavium,wait-mode;
-                               cavium,bus-width = <16>;
-                       };
-
-                       flash0: nor@0,0 {
-                               compatible = "cfi-flash";
-                               reg = <0 0 0x800000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                       };
-
                        led0: led-display@4,0 {
                                compatible = "avago,hdsp-253x";
                                reg = <4 0x20 0x20>, <4 0 0x20>;
                        };
                };
 
-               dma0: dma-engine@1180000000100 {
-                       compatible = "cavium,octeon-5750-bootbus-dma";
-                       reg = <0x11800 0x00000100 0x0 0x8>;
-                       interrupts = <0 63>;
-               };
-               dma1: dma-engine@1180000000108 {
-                       compatible = "cavium,octeon-5750-bootbus-dma";
-                       reg = <0x11800 0x00000108 0x0 0x8>;
-                       interrupts = <0 63>;
-               };
-
                uctl: uctl@118006f000000 {
                        compatible = "cavium,octeon-6335-uctl";
                        reg = <0x11800 0x6f000000 0x0 0x100>;
                };
 
                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>;
-                       };
                };
        };
 
diff --git a/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi
new file mode 100644 (file)
index 0000000..5302148
--- /dev/null
@@ -0,0 +1,231 @@
+/* OCTEON 3XXX DTS common parts. */
+
+/dts-v1/;
+
+/ {
+       compatible = "cavium,octeon-3860";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&ciu>;
+
+       soc@0 {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges; /* Direct mapping */
+
+               ciu: interrupt-controller@1070000000000 {
+                       compatible = "cavium,octeon-3860-ciu";
+                       interrupt-controller;
+                       /* Interrupts are specified by two parts:
+                        * 1) Controller register (0 or 1)
+                        * 2) Bit within the register (0..63)
+                        */
+                       #interrupt-cells = <2>;
+                       reg = <0x10700 0x00000000 0x0 0x7000>;
+               };
+
+               gpio: gpio-controller@1070000000800 {
+                       #gpio-cells = <2>;
+                       compatible = "cavium,octeon-3860-gpio";
+                       reg = <0x10700 0x00000800 0x0 0x100>;
+                       gpio-controller;
+                       /* Interrupts are specified by two parts:
+                        * 1) GPIO pin number (0..15)
+                        * 2) Triggering (1 - edge rising
+                        *                2 - edge falling
+                        *                4 - level active high
+                        *                8 - level active low)
+                        */
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       /* The GPIO pin connect to 16 consecutive CUI bits */
+                       interrupts = <0 16>, <0 17>, <0 18>, <0 19>,
+                                    <0 20>, <0 21>, <0 22>, <0 23>,
+                                    <0 24>, <0 25>, <0 26>, <0 27>,
+                                    <0 28>, <0 29>, <0 30>, <0 31>;
+               };
+
+               smi0: mdio@1180000001800 {
+                       compatible = "cavium,octeon-3860-mdio";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x11800 0x00001800 0x0 0x40>;
+               };
+
+               pip: pip@11800a0000000 {
+                       compatible = "cavium,octeon-3860-pip";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x11800 0xa0000000 0x0 0x2000>;
+
+                       interface@0 {
+                               compatible = "cavium,octeon-3860-pip-interface";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0>; /* interface */
+
+                               ethernet@0 {
+                                       compatible = "cavium,octeon-3860-pip-port";
+                                       reg = <0x0>; /* Port */
+                                       local-mac-address = [ 00 00 00 00 00 00 ];
+                               };
+                               ethernet@1 {
+                                       compatible = "cavium,octeon-3860-pip-port";
+                                       reg = <0x1>; /* Port */
+                                       local-mac-address = [ 00 00 00 00 00 00 ];
+                               };
+                               ethernet@2 {
+                                       compatible = "cavium,octeon-3860-pip-port";
+                                       reg = <0x2>; /* Port */
+                                       local-mac-address = [ 00 00 00 00 00 00 ];
+                               };
+                       };
+
+                       interface@1 {
+                               compatible = "cavium,octeon-3860-pip-interface";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <1>; /* interface */
+                       };
+               };
+
+               twsi0: i2c@1180000001000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "cavium,octeon-3860-twsi";
+                       reg = <0x11800 0x00001000 0x0 0x200>;
+                       interrupts = <0 45>;
+                       clock-frequency = <100000>;
+               };
+
+               uart0: serial@1180000000800 {
+                       compatible = "cavium,octeon-3860-uart","ns16550";
+                       reg = <0x11800 0x00000800 0x0 0x400>;
+                       clock-frequency = <0>;
+                       current-speed = <115200>;
+                       reg-shift = <3>;
+                       interrupts = <0 34>;
+               };
+
+               bootbus: bootbus@1180000000000 {
+                       compatible = "cavium,octeon-3860-bootbus";
+                       reg = <0x11800 0x00000000 0x0 0x200>;
+                       /* The chip select number and offset */
+                       #address-cells = <2>;
+                       /* The size of the chip select region */
+                       #size-cells = <1>;
+                       ranges = <0 0  0x0 0x1f400000  0xc00000>,
+                                <1 0  0x10000 0x30000000  0>,
+                                <2 0  0x10000 0x40000000  0>,
+                                <3 0  0x10000 0x50000000  0>,
+                                <4 0  0x0 0x1d020000  0x10000>,
+                                <5 0  0x0 0x1d040000  0x10000>,
+                                <6 0  0x0 0x1d050000  0x10000>,
+                                <7 0  0x10000 0x90000000  0>;
+
+                       cavium,cs-config@0 {
+                               compatible = "cavium,octeon-3860-bootbus-config";
+                               cavium,cs-index = <0>;
+                               cavium,t-adr  = <20>;
+                               cavium,t-ce   = <60>;
+                               cavium,t-oe   = <60>;
+                               cavium,t-we   = <45>;
+                               cavium,t-rd-hld = <35>;
+                               cavium,t-wr-hld = <45>;
+                               cavium,t-pause  = <0>;
+                               cavium,t-wait   = <0>;
+                               cavium,t-page   = <35>;
+                               cavium,t-rd-dly = <0>;
+
+                               cavium,pages     = <0>;
+                               cavium,bus-width = <8>;
+                       };
+                       cavium,cs-config@4 {
+                               compatible = "cavium,octeon-3860-bootbus-config";
+                               cavium,cs-index = <4>;
+                               cavium,t-adr  = <320>;
+                               cavium,t-ce   = <320>;
+                               cavium,t-oe   = <320>;
+                               cavium,t-we   = <320>;
+                               cavium,t-rd-hld = <320>;
+                               cavium,t-wr-hld = <320>;
+                               cavium,t-pause  = <320>;
+                               cavium,t-wait   = <320>;
+                               cavium,t-page   = <320>;
+                               cavium,t-rd-dly = <0>;
+
+                               cavium,pages     = <0>;
+                               cavium,bus-width = <8>;
+                       };
+                       cavium,cs-config@5 {
+                               compatible = "cavium,octeon-3860-bootbus-config";
+                               cavium,cs-index = <5>;
+                               cavium,t-adr  = <5>;
+                               cavium,t-ce   = <300>;
+                               cavium,t-oe   = <125>;
+                               cavium,t-we   = <150>;
+                               cavium,t-rd-hld = <100>;
+                               cavium,t-wr-hld = <30>;
+                               cavium,t-pause  = <0>;
+                               cavium,t-wait   = <30>;
+                               cavium,t-page   = <320>;
+                               cavium,t-rd-dly = <0>;
+
+                               cavium,pages     = <0>;
+                               cavium,bus-width = <16>;
+                       };
+                       cavium,cs-config@6 {
+                               compatible = "cavium,octeon-3860-bootbus-config";
+                               cavium,cs-index = <6>;
+                               cavium,t-adr  = <5>;
+                               cavium,t-ce   = <300>;
+                               cavium,t-oe   = <270>;
+                               cavium,t-we   = <150>;
+                               cavium,t-rd-hld = <100>;
+                               cavium,t-wr-hld = <70>;
+                               cavium,t-pause  = <0>;
+                               cavium,t-wait   = <0>;
+                               cavium,t-page   = <320>;
+                               cavium,t-rd-dly = <0>;
+
+                               cavium,pages     = <0>;
+                               cavium,wait-mode;
+                               cavium,bus-width = <16>;
+                       };
+
+                       flash0: nor@0,0 {
+                               compatible = "cfi-flash";
+                               reg = <0 0 0x800000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                       };
+               };
+
+               dma0: dma-engine@1180000000100 {
+                       compatible = "cavium,octeon-5750-bootbus-dma";
+                       reg = <0x11800 0x00000100 0x0 0x8>;
+                       interrupts = <0 63>;
+               };
+
+               dma1: dma-engine@1180000000108 {
+                       compatible = "cavium,octeon-5750-bootbus-dma";
+                       reg = <0x11800 0x00000108 0x0 0x8>;
+                       interrupts = <0 63>;
+               };
+
+               usbn: usbn@1180068000000 {
+                       compatible = "cavium,octeon-5750-usbn";
+                       reg = <0x11800 0x68000000 0x0 0x1000>;
+                       ranges; /* Direct mapping */
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+
+                       usbc@16f0010000000 {
+                               compatible = "cavium,octeon-5750-usbc";
+                               reg = <0x16f00 0x10000000 0x0 0x80000>;
+                               interrupts = <0 56>;
+                       };
+               };
+       };
+};
diff --git a/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts b/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts
new file mode 100644 (file)
index 0000000..243e5dc
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Device tree source for EdgeRouter Lite.
+ *
+ * Written by: Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/include/ "octeon_3xxx.dtsi"
+
+/ {
+       model = "ubnt,e100";
+
+       soc@0 {
+               smi0: mdio@1180000001800 {
+                       phy5: ethernet-phy@5 {
+                               reg = <5>;
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                       };
+                       phy6: ethernet-phy@6 {
+                               reg = <6>;
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                       };
+                       phy7: ethernet-phy@7 {
+                               reg = <7>;
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                       };
+               };
+
+               pip: pip@11800a0000000 {
+                       interface@0 {
+                               ethernet@0 {
+                                       phy-handle = <&phy7>;
+                               };
+                               ethernet@1 {
+                                       phy-handle = <&phy6>;
+                               };
+                               ethernet@2 {
+                                       phy-handle = <&phy5>;
+                               };
+                       };
+               };
+
+               uart0: serial@1180000000800 {
+                       clock-frequency = <500000000>;
+               };
+
+               usbn: usbn@1180068000000 {
+                       refclk-frequency = <12000000>;
+                       refclk-type = "crystal";
+               };
+       };
+
+       aliases {
+               pip = &pip;
+       };
+};
index 8b2437cd019f3688feb0ed7bc0a290ec57d008a7..4a9c8f2a72d6b736f25a314e360412297dba69ac 100644 (file)
                clocks = <&ext>, <&cgu JZ4740_CLK_UART1>;
                clock-names = "baud", "module";
        };
+
+       uhc: uhc@13030000 {
+               compatible = "ingenic,jz4740-ohci", "generic-ohci";
+               reg = <0x13030000 0x1000>;
+
+               clocks = <&cgu JZ4740_CLK_UHC>;
+               assigned-clocks = <&cgu JZ4740_CLK_UHC>;
+               assigned-clock-rates = <48000000>;
+
+               interrupt-parent = <&intc>;
+               interrupts = <3>;
+
+               status = "disabled";
+       };
 };
index 143b8a37b5e41358f3faa814375869b058c9fee7..b59962585ddea9d41d46082f557bb7eab4c59918 100644 (file)
@@ -52,7 +52,7 @@
                };
 
                gpio: pinmux@E100B10 {
-                       compatible = "lantiq,pinctrl-xway";
+                       compatible = "lantiq,danube-pinctrl";
                        pinctrl-names = "default";
                        pinctrl-0 = <&state_default>;
 
diff --git a/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi b/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi
deleted file mode 100644 (file)
index ef13350..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Device Tree Source for PIC32MZDA clock data
- *
- * Purna Chandra Mandal <purna.mandal@microchip.com>
- * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
- *
- * Licensed under GPLv2 or later.
- */
-
-/* all fixed rate clocks */
-
-/ {
-       POSC:posc_clk { /* On-chip primary oscillator */
-               #clock-cells = <0>;
-               compatible = "fixed-clock";
-               clock-frequency = <24000000>;
-       };
-
-       FRC:frc_clk { /* internal FRC oscillator */
-               #clock-cells = <0>;
-               compatible = "fixed-clock";
-               clock-frequency = <8000000>;
-       };
-
-       BFRC:bfrc_clk { /* internal backup FRC oscillator */
-               #clock-cells = <0>;
-               compatible = "fixed-clock";
-               clock-frequency = <8000000>;
-       };
-
-       LPRC:lprc_clk { /* internal low-power FRC oscillator */
-               #clock-cells = <0>;
-               compatible = "fixed-clock";
-               clock-frequency = <32000>;
-       };
-
-       /* UPLL provides clock to USBCORE */
-       UPLL:usb_phy_clk {
-               #clock-cells = <0>;
-               compatible = "fixed-clock";
-               clock-frequency = <24000000>;
-               clock-output-names = "usbphy_clk";
-       };
-
-       TxCKI:txcki_clk { /* external clock input on TxCLKI pin */
-               #clock-cells = <0>;
-               compatible = "fixed-clock";
-               clock-frequency = <4000000>;
-               status = "disabled";
-       };
-
-       /* external clock input on REFCLKIx pin */
-       REFIx:refix_clk {
-               #clock-cells = <0>;
-               compatible = "fixed-clock";
-               clock-frequency = <24000000>;
-               status = "disabled";
-       };
-
-       /* PIC32 specific clks */
-       pic32_clktree {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               reg = <0x1f801200 0x200>;
-               compatible = "microchip,pic32mzda-clk";
-               ranges = <0 0x1f801200 0x200>;
-
-               /* secondary oscillator; external input on SOSCI pin */
-               SOSC:sosc_clk@0 {
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-sosc";
-                       clock-frequency = <32768>;
-                       reg = <0x000 0x10>,   /* enable reg */
-                             <0x1d0 0x10>; /* status reg */
-                       microchip,bit-mask = <0x02>; /* enable mask */
-                       microchip,status-bit-mask = <0x10>; /* status-mask*/
-               };
-
-               FRCDIV:frcdiv_clk {
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-frcdivclk";
-                       clocks = <&FRC>;
-                       clock-output-names = "frcdiv_clk";
-               };
-
-               /* System PLL clock */
-               SYSPLL:spll_clk@020 {
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-syspll";
-                       reg = <0x020 0x10>, /* SPLL register */
-                             <0x1d0 0x10>; /* CLKSTAT register */
-                       clocks = <&POSC>, <&FRC>;
-                       clock-output-names = "sys_pll";
-                       microchip,status-bit-mask = <0x80>; /* SPLLRDY */
-               };
-
-               /* system clock; mux with postdiv & slew */
-               SYSCLK:sys_clk@1c0 {
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-sysclk-v2";
-                       reg = <0x1c0 0x04>; /* SLEWCON */
-                       clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>,
-                                <&LPRC>, <&FRCDIV>;
-                       microchip,clock-indices = <0>, <1>, <2>, <4>,
-                                                 <5>, <7>;
-                       clock-output-names = "sys_clk";
-               };
-
-               /* Peripheral bus1 clock */
-               PBCLK1:pb1_clk@140 {
-                       reg = <0x140 0x10>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-pbclk";
-                       clocks = <&SYSCLK>;
-                       clock-output-names = "pb1_clk";
-                       /* used by system modules, not gateable */
-                       microchip,ignore-unused;
-               };
-
-               /* Peripheral bus2 clock */
-               PBCLK2:pb2_clk@150 {
-                       reg = <0x150 0x10>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-pbclk";
-                       clocks = <&SYSCLK>;
-                       clock-output-names = "pb2_clk";
-                       /* avoid gating even if unused */
-                       microchip,ignore-unused;
-               };
-
-               /* Peripheral bus3 clock */
-               PBCLK3:pb3_clk@160 {
-                       reg = <0x160 0x10>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-pbclk";
-                       clocks = <&SYSCLK>;
-                       clock-output-names = "pb3_clk";
-               };
-
-               /* Peripheral bus4 clock(I/O ports, GPIO) */
-               PBCLK4:pb4_clk@170 {
-                       reg = <0x170 0x10>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-pbclk";
-                       clocks = <&SYSCLK>;
-                       clock-output-names = "pb4_clk";
-               };
-
-               /* Peripheral bus clock */
-               PBCLK5:pb5_clk@180 {
-                       reg = <0x180 0x10>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-pbclk";
-                       clocks = <&SYSCLK>;
-                       clock-output-names = "pb5_clk";
-               };
-
-               /* Peripheral Bus6 clock; */
-               PBCLK6:pb6_clk@190 {
-                       reg = <0x190 0x10>;
-                       compatible = "microchip,pic32mzda-pbclk";
-                       clocks = <&SYSCLK>;
-                       #clock-cells = <0>;
-               };
-
-               /* Peripheral bus7 clock */
-               PBCLK7:pb7_clk@1a0 {
-                       reg = <0x1a0 0x10>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-pbclk";
-                       /* CPU is driven by this clock; so named */
-                       clock-output-names = "cpu_clk";
-                       clocks = <&SYSCLK>;
-               };
-
-               /* Reference Oscillator clock for SPI/I2S */
-               REFCLKO1:refo1_clk@80 {
-                       reg = <0x080 0x20>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-refoclk";
-                       clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-                                <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-                       microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-                                                 <5>, <7>, <8>, <9>;
-                       clock-output-names = "refo1_clk";
-               };
-
-               /* Reference Oscillator clock for SQI */
-               REFCLKO2:refo2_clk@a0 {
-                       reg = <0x0a0 0x20>;
-                       #clock-cells = <0>;
-                       compatible = "microchip,pic32mzda-refoclk";
-                       clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-                                <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-                       microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-                                                 <5>, <7>, <8>, <9>;
-                       clock-output-names = "refo2_clk";
-               };
-
-               /* Reference Oscillator clock, ADC */
-               REFCLKO3:refo3_clk@c0 {
-                       reg = <0x0c0 0x20>;
-                       compatible = "microchip,pic32mzda-refoclk";
-                       clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-                                <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-                       microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-                                                 <5>, <7>, <8>, <9>;
-                       #clock-cells = <0>;
-                       clock-output-names = "refo3_clk";
-               };
-
-               /* Reference Oscillator clock */
-               REFCLKO4:refo4_clk@e0 {
-                       reg = <0x0e0 0x20>;
-                       compatible = "microchip,pic32mzda-refoclk";
-                       clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-                                <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-                       microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-                                                 <5>, <7>, <8>, <9>;
-                       #clock-cells = <0>;
-                       clock-output-names = "refo4_clk";
-               };
-
-               /* Reference Oscillator clock, LCD */
-               REFCLKO5:refo5_clk@100 {
-                       reg = <0x100 0x20>;
-                       compatible = "microchip,pic32mzda-refoclk";
-                       clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>,
-                                <&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>;
-                       microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-                                                 <5>, <7>, <8>, <9>;
-                       #clock-cells = <0>;
-                       clock-output-names = "refo5_clk";
-               };
-       };
-};
index ad9e3318c2ce83ac9ca0c74520fb9157fc6594a9..5353a639c4fb2180d6d4431b8fb0e9692f5fe89c 100644 (file)
@@ -6,11 +6,9 @@
  * published by the Free Software Foundation.
  *
  */
-
+#include <dt-bindings/clock/microchip,pic32-clock.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
-#include "pic32mzda-clk.dtsi"
-
 / {
        #address-cells = <1>;
        #size-cells = <1>;
                interrupts = <0 IRQ_TYPE_EDGE_RISING>;
        };
 
+       /* external clock input on TxCLKI pin */
+       txcki: txcki_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <4000000>;
+               status = "disabled";
+       };
+
+       /* external input on REFCLKIx pin */
+       refix: refix_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <24000000>;
+               status = "disabled";
+       };
+
+       rootclk: clock-controller@1f801200 {
+               compatible = "microchip,pic32mzda-clk";
+               reg = <0x1f801200 0x200>;
+               #clock-cells = <1>;
+               microchip,pic32mzda-sosc;
+       };
+
        evic: interrupt-controller@1f810000 {
                compatible = "microchip,pic32mzda-evic";
                interrupt-controller;
@@ -63,7 +84,7 @@
                #size-cells = <1>;
                compatible = "microchip,pic32mzda-pinctrl";
                reg = <0x1f801400 0x400>;
-               clocks = <&PBCLK1>;
+               clocks = <&rootclk PB1CLK>;
        };
 
        /* PORTA */
@@ -75,7 +96,7 @@
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <0>;
                gpio-ranges = <&pic32_pinctrl 0 0 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <1>;
                gpio-ranges = <&pic32_pinctrl 0 16 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <2>;
                gpio-ranges = <&pic32_pinctrl 0 32 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <3>;
                gpio-ranges = <&pic32_pinctrl 0 48 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <4>;
                gpio-ranges = <&pic32_pinctrl 0 64 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <5>;
                gpio-ranges = <&pic32_pinctrl 0 80 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <6>;
                gpio-ranges = <&pic32_pinctrl 0 96 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <7>;
                gpio-ranges = <&pic32_pinctrl 0 112 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <8>;
                gpio-ranges = <&pic32_pinctrl 0 128 16>;
        };
                gpio-controller;
                interrupt-controller;
                #interrupt-cells = <2>;
-               clocks = <&PBCLK4>;
+               clocks = <&rootclk PB4CLK>;
                microchip,gpio-bank = <9>;
                gpio-ranges = <&pic32_pinctrl 0 144 16>;
        };
                compatible = "microchip,pic32mzda-sdhci";
                reg = <0x1f8ec000 0x100>;
                interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&REFCLKO4>, <&PBCLK5>;
+               clocks = <&rootclk REF4CLK>, <&rootclk PB5CLK>;
                clock-names = "base_clk", "sys_clk";
                bus-width = <4>;
                cap-sd-highspeed;
                interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
                        <113 IRQ_TYPE_LEVEL_HIGH>,
                        <114 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&PBCLK2>;
+               clocks = <&rootclk PB2CLK>;
                status = "disabled";
        };
 
                interrupts = <145 IRQ_TYPE_LEVEL_HIGH>,
                        <146 IRQ_TYPE_LEVEL_HIGH>,
                        <147 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&PBCLK2>;
+               clocks = <&rootclk PB2CLK>;
                status = "disabled";
        };
 
                interrupts = <157 IRQ_TYPE_LEVEL_HIGH>,
                        <158 IRQ_TYPE_LEVEL_HIGH>,
                        <159 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&PBCLK2>;
+               clocks = <&rootclk PB2CLK>;
                status = "disabled";
        };
 
                interrupts = <170 IRQ_TYPE_LEVEL_HIGH>,
                        <171 IRQ_TYPE_LEVEL_HIGH>,
                        <172 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&PBCLK2>;
+               clocks = <&rootclk PB2CLK>;
                status = "disabled";
        };
 
                interrupts = <179 IRQ_TYPE_LEVEL_HIGH>,
                        <180 IRQ_TYPE_LEVEL_HIGH>,
                        <181 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&PBCLK2>;
+               clocks = <&rootclk PB2CLK>;
                status = "disabled";
        };
 
                interrupts = <188 IRQ_TYPE_LEVEL_HIGH>,
                        <189 IRQ_TYPE_LEVEL_HIGH>,
                        <190 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&PBCLK2>;
+               clocks = <&rootclk PB2CLK>;
                status = "disabled";
        };
 };
index 5d434a50e85b81e014b7f2ce7be4483ef689f8e2..fc740102852e034084969a2c936ad2744ea7ab7d 100644 (file)
@@ -95,8 +95,9 @@
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_sdhc1>;
        status = "okay";
-       assigned-clocks = <&REFCLKO2>,<&REFCLKO4>,<&REFCLKO5>;
-       assigned-clock-rates = <50000000>,<25000000>,<40000000>;
+       assigned-clocks = <&rootclk REF2CLK>, <&rootclk REF4CLK>,
+               <&rootclk REF5CLK>;
+       assigned-clock-rates = <50000000>, <25000000>, <40000000>;
 };
 
 &pic32_pinctrl {
index 2d61455d585d2d59f87616d872db5297b98b2ce5..63a9ddf048c94cbf527df0134bf38fe2d37da17d 100644 (file)
@@ -1,8 +1,9 @@
 # All DTBs
 dtb-$(CONFIG_ATH79)                    += ar9132_tl_wr1043nd_v1.dtb
-
-# Select a DTB to build in the kernel
-obj-$(CONFIG_DTB_TL_WR1043ND_V1)       += ar9132_tl_wr1043nd_v1.dtb.o
+dtb-$(CONFIG_ATH79)                    += ar9331_dpt_module.dtb
+dtb-$(CONFIG_ATH79)                    += ar9331_dragino_ms14.dtb
+dtb-$(CONFIG_ATH79)                    += ar9331_omega.dtb
+dtb-$(CONFIG_ATH79)                    += ar9331_tl_mr3020.dtb
 
 # Force kbuild to make empty built-in.o if necessary
 obj-                           += dummy.o
index 3c2ed9ee5b2f89d3f8b17eef1328b1dbb68702eb..302f0a8d29882627d1135331325c53ae05e8be12 100644 (file)
@@ -1,3 +1,5 @@
+#include <dt-bindings/clock/ath79-clk.h>
+
 / {
        compatible = "qca,ar9132";
 
@@ -11,6 +13,7 @@
                cpu@0 {
                        device_type = "cpu";
                        compatible = "mips,mips24Kc";
+                       clocks = <&pll ATH79_CLK_CPU>;
                        reg = <0>;
                };
        };
                                #qca,ddr-wb-channel-cells = <1>;
                        };
 
-                       uart@18020000 {
+                       uart: uart@18020000 {
                                compatible = "ns8250";
                                reg = <0x18020000 0x20>;
                                interrupts = <3>;
 
-                               clocks = <&pll 2>;
+                               clocks = <&pll ATH79_CLK_AHB>;
                                clock-names = "uart";
 
                                reg-io-width = <4>;
                                clock-output-names = "cpu", "ddr", "ahb";
                        };
 
-                       wdt@18060008 {
+                       wdt: wdt@18060008 {
                                compatible = "qca,ar7130-wdt";
                                reg = <0x18060008 0x8>;
 
                                interrupts = <4>;
 
-                               clocks = <&pll 2>;
+                               clocks = <&pll ATH79_CLK_AHB>;
                                clock-names = "wdt";
                        };
 
                        };
                };
 
-               usb@1b000100 {
+               usb: usb@1b000100 {
                        compatible = "qca,ar7100-ehci", "generic-ehci";
                        reg = <0x1b000100 0x100>;
 
                        status = "disabled";
                };
 
-               spi@1f000000 {
+               spi: spi@1f000000 {
                        compatible = "qca,ar9132-spi", "qca,ar7100-spi";
                        reg = <0x1f000000 0x10>;
 
-                       clocks = <&pll 2>;
+                       clocks = <&pll ATH79_CLK_AHB>;
                        clock-names = "ahb";
 
                        status = "disabled";
index 4f1540e5f963493201406f80e11de3e9d198d4c1..3c3b7ce5737be27e5eb14cbb34c40dd59200f20f 100644 (file)
@@ -9,10 +9,6 @@
        compatible = "tplink,tl-wr1043nd-v1", "qca,ar9132";
        model = "TP-Link TL-WR1043ND Version 1";
 
-       alias {
-               serial0 = "/ahb/apb/uart@18020000";
-       };
-
        memory@0 {
                device_type = "memory";
                reg = <0x0 0x2000000>;
                clock-frequency = <40000000>;
        };
 
-       ahb {
-               apb {
-                       uart@18020000 {
-                               status = "okay";
-                       };
-
-                       pll-controller@18050000 {
-                               clocks = <&extosc>;
-                       };
-               };
-
-               usb@1b000100 {
-                       status = "okay";
-               };
-
-               spi@1f000000 {
-                       status = "okay";
-                       num-cs = <1>;
-
-                       flash@0 {
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               compatible = "s25sl064a";
-                               reg = <0>;
-                               spi-max-frequency = <25000000>;
-
-                               partition@0 {
-                                       label = "u-boot";
-                                       reg = <0x000000 0x020000>;
-                               };
-
-                               partition@1 {
-                                       label = "firmware";
-                                       reg = <0x020000 0x7D0000>;
-                               };
-
-                               partition@2 {
-                                       label = "art";
-                                       reg = <0x7F0000 0x010000>;
-                                       read-only;
-                               };
-                       };
-               };
-       };
-
-       usb-phy {
-               status = "okay";
-       };
-
        gpio-keys {
                compatible = "gpio-keys-polled";
                #address-cells = <1>;
                };
        };
 };
+
+&uart {
+       status = "okay";
+};
+
+&pll {
+       clocks = <&extosc>;
+};
+
+&usb {
+       status = "okay";
+};
+
+&usb_phy {
+       status = "okay";
+};
+
+&spi {
+       status = "okay";
+       num-cs = <1>;
+
+       flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "s25sl064a";
+               reg = <0>;
+               spi-max-frequency = <25000000>;
+
+               partition@0 {
+                       label = "u-boot";
+                       reg = <0x000000 0x020000>;
+               };
+
+               partition@1 {
+                       label = "firmware";
+                       reg = <0x020000 0x7D0000>;
+               };
+
+               partition@2 {
+                       label = "art";
+                       reg = <0x7F0000 0x010000>;
+                       read-only;
+               };
+       };
+};
diff --git a/arch/mips/boot/dts/qca/ar9331.dtsi b/arch/mips/boot/dts/qca/ar9331.dtsi
new file mode 100644 (file)
index 0000000..cf47ed4
--- /dev/null
@@ -0,0 +1,155 @@
+#include <dt-bindings/clock/ath79-clk.h>
+
+/ {
+       compatible = "qca,ar9331";
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,mips24Kc";
+                       clocks = <&pll ATH79_CLK_CPU>;
+                       reg = <0>;
+               };
+       };
+
+       cpuintc: interrupt-controller {
+               compatible = "qca,ar7100-cpu-intc";
+
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               qca,ddr-wb-channel-interrupts = <2>, <3>;
+               qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>;
+       };
+
+       ref: ref {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+       };
+
+       ahb {
+               compatible = "simple-bus";
+               ranges;
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               interrupt-parent = <&cpuintc>;
+
+               apb {
+                       compatible = "simple-bus";
+                       ranges;
+
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       interrupt-parent = <&miscintc>;
+
+                       ddr_ctrl: memory-controller@18000000 {
+                               compatible = "qca,ar7240-ddr-controller";
+                               reg = <0x18000000 0x100>;
+
+                               #qca,ddr-wb-channel-cells = <1>;
+                       };
+
+                       uart: uart@18020000 {
+                               compatible = "qca,ar9330-uart";
+                               reg = <0x18020000 0x14>;
+
+                               interrupts = <3>;
+
+                               clocks = <&ref>;
+                               clock-names = "uart";
+
+                               status = "disabled";
+                       };
+
+                       gpio: gpio@18040000 {
+                               compatible = "qca,ar7100-gpio";
+                               reg = <0x18040000 0x34>;
+                               interrupts = <2>;
+
+                               ngpios = <30>;
+
+                               gpio-controller;
+                               #gpio-cells = <2>;
+
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+
+                               status = "disabled";
+                       };
+
+                       pll: pll-controller@18050000 {
+                               compatible = "qca,ar9330-pll";
+                               reg = <0x18050000 0x100>;
+
+                               clocks = <&ref>;
+                               clock-names = "ref";
+
+                               #clock-cells = <1>;
+                       };
+
+                       miscintc: interrupt-controller@18060010 {
+                               compatible = "qca,ar7240-misc-intc";
+                               reg = <0x18060010 0x4>;
+
+                               interrupt-parent = <&cpuintc>;
+                               interrupts = <6>;
+
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                       };
+
+                       rst: reset-controller@1806001c {
+                               compatible = "qca,ar7100-reset";
+                               reg = <0x1806001c 0x4>;
+
+                               #reset-cells = <1>;
+                       };
+               };
+
+               usb: usb@1b000100 {
+                       compatible = "chipidea,usb2";
+                       reg = <0x1b000000 0x200>;
+
+                       interrupts = <3>;
+                       resets = <&rst 5>;
+
+                       phy-names = "usb-phy";
+                       phys = <&usb_phy>;
+
+                       status = "disabled";
+               };
+
+               spi: spi@1f000000 {
+                       compatible = "qca,ar7100-spi";
+                       reg = <0x1f000000 0x10>;
+
+                       clocks = <&pll ATH79_CLK_AHB>;
+                       clock-names = "ahb";
+
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       status = "disabled";
+               };
+       };
+
+       usb_phy: usb-phy {
+               compatible = "qca,ar7100-usb-phy";
+
+               reset-names = "usb-phy", "usb-suspend-override";
+               resets = <&rst 4>, <&rst 3>;
+
+               #phy-cells = <0>;
+
+               status = "disabled";
+       };
+};
diff --git a/arch/mips/boot/dts/qca/ar9331_dpt_module.dts b/arch/mips/boot/dts/qca/ar9331_dpt_module.dts
new file mode 100644 (file)
index 0000000..98e7450
--- /dev/null
@@ -0,0 +1,78 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+       model = "DPTechnics DPT-Module";
+       compatible = "dptechnics,dpt-module";
+
+       aliases {
+               serial0 = &uart;
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x4000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               system {
+                       label = "dpt-module:green:system";
+                       gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+       };
+
+       gpio-keys-polled {
+               compatible = "gpio-keys-polled";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <100>;
+
+               button@0 {
+                       label = "reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
+
+&ref {
+       clock-frequency = <25000000>;
+};
+
+&uart {
+       status = "okay";
+};
+
+&gpio {
+       status = "okay";
+};
+
+&usb {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usb_phy {
+       status = "okay";
+};
+
+&spi {
+       num-chipselects = <1>;
+       status = "okay";
+
+       /* Winbond 25Q128FVSG SPI flash */
+       spiflash: w25q128@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "winbond,w25q128", "jedec,spi-nor";
+               spi-max-frequency = <104000000>;
+               reg = <0>;
+       };
+};
diff --git a/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts b/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts
new file mode 100644 (file)
index 0000000..56f8320
--- /dev/null
@@ -0,0 +1,102 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+       model = "Dragino MS14 (Dragino 2)";
+       compatible = "dragino,ms14";
+
+       aliases {
+               serial0 = &uart;
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x4000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               wlan {
+                       label = "dragino2:red:wlan";
+                       gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               lan {
+                       label = "dragino2:red:lan";
+                       gpios = <&gpio 13 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               wan {
+                       label = "dragino2:red:wan";
+                       gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               system {
+                       label = "dragino2:red:system";
+                       gpios = <&gpio 28 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+       };
+
+       gpio-keys-polled {
+               compatible = "gpio-keys-polled";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <100>;
+
+               button@0 {
+                       label = "jumpstart";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+               };
+
+               button@1 {
+                       label = "reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
+
+&ref {
+       clock-frequency = <25000000>;
+};
+
+&uart {
+       status = "okay";
+};
+
+&gpio {
+       status = "okay";
+};
+
+&usb {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usb_phy {
+       status = "okay";
+};
+
+&spi {
+       num-chipselects = <1>;
+       status = "okay";
+
+       /* Winbond 25Q128BVFG SPI flash */
+       spiflash: w25q128@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "winbond,w25q128", "jedec,spi-nor";
+               spi-max-frequency = <104000000>;
+               reg = <0>;
+       };
+};
diff --git a/arch/mips/boot/dts/qca/ar9331_omega.dts b/arch/mips/boot/dts/qca/ar9331_omega.dts
new file mode 100644 (file)
index 0000000..b2be3b0
--- /dev/null
@@ -0,0 +1,78 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+       model = "Onion Omega";
+       compatible = "onion,omega";
+
+       aliases {
+               serial0 = &uart;
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x4000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               system {
+                       label = "onion:amber:system";
+                       gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+       };
+
+       gpio-keys-polled {
+               compatible = "gpio-keys-polled";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <100>;
+
+               button@0 {
+                       label = "reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
+
+&ref {
+       clock-frequency = <25000000>;
+};
+
+&uart {
+       status = "okay";
+};
+
+&gpio {
+       status = "okay";
+};
+
+&usb {
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usb_phy {
+       status = "okay";
+};
+
+&spi {
+       num-chipselects = <1>;
+       status = "okay";
+
+       /* Winbond 25Q128FVSG SPI flash */
+       spiflash: w25q128@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "winbond,w25q128", "jedec,spi-nor";
+               spi-max-frequency = <104000000>;
+               reg = <0>;
+       };
+};
diff --git a/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts b/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts
new file mode 100644 (file)
index 0000000..919cf3b
--- /dev/null
@@ -0,0 +1,118 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+       model = "TP-Link TL-MR3020";
+       compatible = "tplink,tl-mr3020";
+
+       aliases {
+               serial0 = &uart;
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x2000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               wlan {
+                       label = "tp-link:green:wlan";
+                       gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               lan {
+                       label = "tp-link:green:lan";
+                       gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               wps {
+                       label = "tp-link:green:wps";
+                       gpios = <&gpio 26 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               led3g {
+                       label = "tp-link:green:3g";
+                       gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+       };
+
+       gpio-keys-polled {
+               compatible = "gpio-keys-polled";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <100>;
+
+               button@0 {
+                       label = "wps";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
+               };
+
+               button@1 {
+                       label = "sw1";
+                       linux,code = <BTN_0>;
+                       gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
+               };
+
+               button@2 {
+                       label = "sw2";
+                       linux,code = <BTN_1>;
+                       gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
+       reg_usb_vbus: reg_usb_vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio 8 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+};
+
+&ref {
+       clock-frequency = <25000000>;
+};
+
+&uart {
+       status = "okay";
+};
+
+&gpio {
+       status = "okay";
+};
+
+&usb {
+       dr_mode = "host";
+       vbus-supply = <&reg_usb_vbus>;
+       status = "okay";
+};
+
+&usb_phy {
+       status = "okay";
+};
+
+&spi {
+       num-chipselects = <1>;
+       status = "okay";
+
+       /* Spansion S25FL032PIF SPI flash */
+       spiflash: s25sl032p@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spansion,s25sl032p", "jedec,spi-nor";
+               spi-max-frequency = <104000000>;
+               reg = <0>;
+       };
+};
diff --git a/arch/mips/boot/tools/.gitignore b/arch/mips/boot/tools/.gitignore
new file mode 100644 (file)
index 0000000..be0ed06
--- /dev/null
@@ -0,0 +1 @@
+relocs
diff --git a/arch/mips/boot/tools/Makefile b/arch/mips/boot/tools/Makefile
new file mode 100644 (file)
index 0000000..d232a68
--- /dev/null
@@ -0,0 +1,8 @@
+
+hostprogs-y    += relocs
+relocs-objs    += relocs_32.o
+relocs-objs    += relocs_64.o
+relocs-objs    += relocs_main.o
+PHONY += relocs
+relocs: $(obj)/relocs
+       @:
diff --git a/arch/mips/boot/tools/relocs.c b/arch/mips/boot/tools/relocs.c
new file mode 100644 (file)
index 0000000..b9cbf78
--- /dev/null
@@ -0,0 +1,680 @@
+/* This is included from relocs_32/64.c */
+
+#define ElfW(type)             _ElfW(ELF_BITS, type)
+#define _ElfW(bits, type)      __ElfW(bits, type)
+#define __ElfW(bits, type)     Elf##bits##_##type
+
+#define Elf_Addr               ElfW(Addr)
+#define Elf_Ehdr               ElfW(Ehdr)
+#define Elf_Phdr               ElfW(Phdr)
+#define Elf_Shdr               ElfW(Shdr)
+#define Elf_Sym                        ElfW(Sym)
+
+static Elf_Ehdr ehdr;
+
+struct relocs {
+       uint32_t        *offset;
+       unsigned long   count;
+       unsigned long   size;
+};
+
+static struct relocs relocs;
+
+struct section {
+       Elf_Shdr       shdr;
+       struct section *link;
+       Elf_Sym        *symtab;
+       Elf_Rel        *reltab;
+       char           *strtab;
+       long           shdr_offset;
+};
+static struct section *secs;
+
+static const char * const regex_sym_kernel = {
+/* Symbols matching these regex's should never be relocated */
+       "^(__crc_)",
+};
+
+static regex_t sym_regex_c;
+
+static int regex_skip_reloc(const char *sym_name)
+{
+       return !regexec(&sym_regex_c, sym_name, 0, NULL, 0);
+}
+
+static void regex_init(void)
+{
+       char errbuf[128];
+       int err;
+
+       err = regcomp(&sym_regex_c, regex_sym_kernel,
+                       REG_EXTENDED|REG_NOSUB);
+
+       if (err) {
+               regerror(err, &sym_regex_c, errbuf, sizeof(errbuf));
+               die("%s", errbuf);
+       }
+}
+
+static const char *rel_type(unsigned type)
+{
+       static const char * const type_name[] = {
+#define REL_TYPE(X)[X] = #X
+               REL_TYPE(R_MIPS_NONE),
+               REL_TYPE(R_MIPS_16),
+               REL_TYPE(R_MIPS_32),
+               REL_TYPE(R_MIPS_REL32),
+               REL_TYPE(R_MIPS_26),
+               REL_TYPE(R_MIPS_HI16),
+               REL_TYPE(R_MIPS_LO16),
+               REL_TYPE(R_MIPS_GPREL16),
+               REL_TYPE(R_MIPS_LITERAL),
+               REL_TYPE(R_MIPS_GOT16),
+               REL_TYPE(R_MIPS_PC16),
+               REL_TYPE(R_MIPS_CALL16),
+               REL_TYPE(R_MIPS_GPREL32),
+               REL_TYPE(R_MIPS_64),
+               REL_TYPE(R_MIPS_HIGHER),
+               REL_TYPE(R_MIPS_HIGHEST),
+               REL_TYPE(R_MIPS_PC21_S2),
+               REL_TYPE(R_MIPS_PC26_S2),
+#undef REL_TYPE
+       };
+       const char *name = "unknown type rel type name";
+
+       if (type < ARRAY_SIZE(type_name) && type_name[type])
+               name = type_name[type];
+       return name;
+}
+
+static const char *sec_name(unsigned shndx)
+{
+       const char *sec_strtab;
+       const char *name;
+
+       sec_strtab = secs[ehdr.e_shstrndx].strtab;
+       if (shndx < ehdr.e_shnum)
+               name = sec_strtab + secs[shndx].shdr.sh_name;
+       else if (shndx == SHN_ABS)
+               name = "ABSOLUTE";
+       else if (shndx == SHN_COMMON)
+               name = "COMMON";
+       else
+               name = "<noname>";
+       return name;
+}
+
+static struct section *sec_lookup(const char *secname)
+{
+       int i;
+
+       for (i = 0; i < ehdr.e_shnum; i++)
+               if (strcmp(secname, sec_name(i)) == 0)
+                       return &secs[i];
+
+       return NULL;
+}
+
+static const char *sym_name(const char *sym_strtab, Elf_Sym *sym)
+{
+       const char *name;
+
+       if (sym->st_name)
+               name = sym_strtab + sym->st_name;
+       else
+               name = sec_name(sym->st_shndx);
+       return name;
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define le16_to_cpu(val) (val)
+#define le32_to_cpu(val) (val)
+#define le64_to_cpu(val) (val)
+#define be16_to_cpu(val) bswap_16(val)
+#define be32_to_cpu(val) bswap_32(val)
+#define be64_to_cpu(val) bswap_64(val)
+
+#define cpu_to_le16(val) (val)
+#define cpu_to_le32(val) (val)
+#define cpu_to_le64(val) (val)
+#define cpu_to_be16(val) bswap_16(val)
+#define cpu_to_be32(val) bswap_32(val)
+#define cpu_to_be64(val) bswap_64(val)
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+#define le16_to_cpu(val) bswap_16(val)
+#define le32_to_cpu(val) bswap_32(val)
+#define le64_to_cpu(val) bswap_64(val)
+#define be16_to_cpu(val) (val)
+#define be32_to_cpu(val) (val)
+#define be64_to_cpu(val) (val)
+
+#define cpu_to_le16(val) bswap_16(val)
+#define cpu_to_le32(val) bswap_32(val)
+#define cpu_to_le64(val) bswap_64(val)
+#define cpu_to_be16(val) (val)
+#define cpu_to_be32(val) (val)
+#define cpu_to_be64(val) (val)
+#endif
+
+static uint16_t elf16_to_cpu(uint16_t val)
+{
+       if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+               return le16_to_cpu(val);
+       else
+               return be16_to_cpu(val);
+}
+
+static uint32_t elf32_to_cpu(uint32_t val)
+{
+       if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+               return le32_to_cpu(val);
+       else
+               return be32_to_cpu(val);
+}
+
+static uint32_t cpu_to_elf32(uint32_t val)
+{
+       if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+               return cpu_to_le32(val);
+       else
+               return cpu_to_be32(val);
+}
+
+#define elf_half_to_cpu(x)     elf16_to_cpu(x)
+#define elf_word_to_cpu(x)     elf32_to_cpu(x)
+
+#if ELF_BITS == 64
+static uint64_t elf64_to_cpu(uint64_t val)
+{
+       if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+               return le64_to_cpu(val);
+       else
+               return be64_to_cpu(val);
+}
+#define elf_addr_to_cpu(x)     elf64_to_cpu(x)
+#define elf_off_to_cpu(x)      elf64_to_cpu(x)
+#define elf_xword_to_cpu(x)    elf64_to_cpu(x)
+#else
+#define elf_addr_to_cpu(x)     elf32_to_cpu(x)
+#define elf_off_to_cpu(x)      elf32_to_cpu(x)
+#define elf_xword_to_cpu(x)    elf32_to_cpu(x)
+#endif
+
+static void read_ehdr(FILE *fp)
+{
+       if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
+               die("Cannot read ELF header: %s\n", strerror(errno));
+
+       if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0)
+               die("No ELF magic\n");
+
+       if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
+               die("Not a %d bit executable\n", ELF_BITS);
+
+       if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
+           (ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
+               die("Unknown ELF Endianness\n");
+
+       if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+               die("Unknown ELF version\n");
+
+       /* Convert the fields to native endian */
+       ehdr.e_type      = elf_half_to_cpu(ehdr.e_type);
+       ehdr.e_machine   = elf_half_to_cpu(ehdr.e_machine);
+       ehdr.e_version   = elf_word_to_cpu(ehdr.e_version);
+       ehdr.e_entry     = elf_addr_to_cpu(ehdr.e_entry);
+       ehdr.e_phoff     = elf_off_to_cpu(ehdr.e_phoff);
+       ehdr.e_shoff     = elf_off_to_cpu(ehdr.e_shoff);
+       ehdr.e_flags     = elf_word_to_cpu(ehdr.e_flags);
+       ehdr.e_ehsize    = elf_half_to_cpu(ehdr.e_ehsize);
+       ehdr.e_phentsize = elf_half_to_cpu(ehdr.e_phentsize);
+       ehdr.e_phnum     = elf_half_to_cpu(ehdr.e_phnum);
+       ehdr.e_shentsize = elf_half_to_cpu(ehdr.e_shentsize);
+       ehdr.e_shnum     = elf_half_to_cpu(ehdr.e_shnum);
+       ehdr.e_shstrndx  = elf_half_to_cpu(ehdr.e_shstrndx);
+
+       if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN))
+               die("Unsupported ELF header type\n");
+
+       if (ehdr.e_machine != ELF_MACHINE)
+               die("Not for %s\n", ELF_MACHINE_NAME);
+
+       if (ehdr.e_version != EV_CURRENT)
+               die("Unknown ELF version\n");
+
+       if (ehdr.e_ehsize != sizeof(Elf_Ehdr))
+               die("Bad Elf header size\n");
+
+       if (ehdr.e_phentsize != sizeof(Elf_Phdr))
+               die("Bad program header entry\n");
+
+       if (ehdr.e_shentsize != sizeof(Elf_Shdr))
+               die("Bad section header entry\n");
+
+       if (ehdr.e_shstrndx >= ehdr.e_shnum)
+               die("String table index out of bounds\n");
+}
+
+static void read_shdrs(FILE *fp)
+{
+       int i;
+       Elf_Shdr shdr;
+
+       secs = calloc(ehdr.e_shnum, sizeof(struct section));
+       if (!secs)
+               die("Unable to allocate %d section headers\n", ehdr.e_shnum);
+
+       if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0)
+               die("Seek to %d failed: %s\n", ehdr.e_shoff, strerror(errno));
+
+       for (i = 0; i < ehdr.e_shnum; i++) {
+               struct section *sec = &secs[i];
+
+               sec->shdr_offset = ftell(fp);
+               if (fread(&shdr, sizeof(shdr), 1, fp) != 1)
+                       die("Cannot read ELF section headers %d/%d: %s\n",
+                           i, ehdr.e_shnum, strerror(errno));
+               sec->shdr.sh_name      = elf_word_to_cpu(shdr.sh_name);
+               sec->shdr.sh_type      = elf_word_to_cpu(shdr.sh_type);
+               sec->shdr.sh_flags     = elf_xword_to_cpu(shdr.sh_flags);
+               sec->shdr.sh_addr      = elf_addr_to_cpu(shdr.sh_addr);
+               sec->shdr.sh_offset    = elf_off_to_cpu(shdr.sh_offset);
+               sec->shdr.sh_size      = elf_xword_to_cpu(shdr.sh_size);
+               sec->shdr.sh_link      = elf_word_to_cpu(shdr.sh_link);
+               sec->shdr.sh_info      = elf_word_to_cpu(shdr.sh_info);
+               sec->shdr.sh_addralign = elf_xword_to_cpu(shdr.sh_addralign);
+               sec->shdr.sh_entsize   = elf_xword_to_cpu(shdr.sh_entsize);
+               if (sec->shdr.sh_link < ehdr.e_shnum)
+                       sec->link = &secs[sec->shdr.sh_link];
+       }
+}
+
+static void read_strtabs(FILE *fp)
+{
+       int i;
+
+       for (i = 0; i < ehdr.e_shnum; i++) {
+               struct section *sec = &secs[i];
+
+               if (sec->shdr.sh_type != SHT_STRTAB)
+                       continue;
+
+               sec->strtab = malloc(sec->shdr.sh_size);
+               if (!sec->strtab)
+                       die("malloc of %d bytes for strtab failed\n",
+                           sec->shdr.sh_size);
+
+               if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
+                       die("Seek to %d failed: %s\n",
+                           sec->shdr.sh_offset, strerror(errno));
+
+               if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) !=
+                   sec->shdr.sh_size)
+                       die("Cannot read symbol table: %s\n", strerror(errno));
+       }
+}
+
+static void read_symtabs(FILE *fp)
+{
+       int i, j;
+
+       for (i = 0; i < ehdr.e_shnum; i++) {
+               struct section *sec = &secs[i];
+               if (sec->shdr.sh_type != SHT_SYMTAB)
+                       continue;
+
+               sec->symtab = malloc(sec->shdr.sh_size);
+               if (!sec->symtab)
+                       die("malloc of %d bytes for symtab failed\n",
+                           sec->shdr.sh_size);
+
+               if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
+                       die("Seek to %d failed: %s\n",
+                           sec->shdr.sh_offset, strerror(errno));
+
+               if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) !=
+                   sec->shdr.sh_size)
+                       die("Cannot read symbol table: %s\n", strerror(errno));
+
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) {
+                       Elf_Sym *sym = &sec->symtab[j];
+
+                       sym->st_name  = elf_word_to_cpu(sym->st_name);
+                       sym->st_value = elf_addr_to_cpu(sym->st_value);
+                       sym->st_size  = elf_xword_to_cpu(sym->st_size);
+                       sym->st_shndx = elf_half_to_cpu(sym->st_shndx);
+               }
+       }
+}
+
+static void read_relocs(FILE *fp)
+{
+       static unsigned long base = 0;
+       int i, j;
+
+       if (!base) {
+               struct section *sec = sec_lookup(".text");
+
+               if (!sec)
+                       die("Could not find .text section\n");
+
+               base = sec->shdr.sh_addr;
+       }
+
+       for (i = 0; i < ehdr.e_shnum; i++) {
+               struct section *sec = &secs[i];
+
+               if (sec->shdr.sh_type != SHT_REL_TYPE)
+                       continue;
+
+               sec->reltab = malloc(sec->shdr.sh_size);
+               if (!sec->reltab)
+                       die("malloc of %d bytes for relocs failed\n",
+                           sec->shdr.sh_size);
+
+               if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
+                       die("Seek to %d failed: %s\n",
+                           sec->shdr.sh_offset, strerror(errno));
+
+               if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) !=
+                   sec->shdr.sh_size)
+                       die("Cannot read symbol table: %s\n", strerror(errno));
+
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+                       Elf_Rel *rel = &sec->reltab[j];
+
+                       rel->r_offset = elf_addr_to_cpu(rel->r_offset);
+                       /* Set offset into kernel image */
+                       rel->r_offset -= base;
+#if (ELF_BITS == 32)
+                       rel->r_info   = elf_xword_to_cpu(rel->r_info);
+#else
+                       /* Convert MIPS64 RELA format - only the symbol
+                        * index needs converting to native endianness
+                        */
+                       rel->r_info   = rel->r_info;
+                       ELF_R_SYM(rel->r_info) = elf32_to_cpu(ELF_R_SYM(rel->r_info));
+#endif
+#if (SHT_REL_TYPE == SHT_RELA)
+                       rel->r_addend = elf_xword_to_cpu(rel->r_addend);
+#endif
+               }
+       }
+}
+
+static void remove_relocs(FILE *fp)
+{
+       int i;
+       Elf_Shdr shdr;
+
+       for (i = 0; i < ehdr.e_shnum; i++) {
+               struct section *sec = &secs[i];
+
+               if (sec->shdr.sh_type != SHT_REL_TYPE)
+                       continue;
+
+               if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0)
+                       die("Seek to %d failed: %s\n",
+                           sec->shdr_offset, strerror(errno));
+
+               if (fread(&shdr, sizeof(shdr), 1, fp) != 1)
+                       die("Cannot read ELF section headers %d/%d: %s\n",
+                           i, ehdr.e_shnum, strerror(errno));
+
+               /* Set relocation section size to 0, effectively removing it.
+                * This is necessary due to lack of support for relocations
+                * in objcopy when creating 32bit elf from 64bit elf.
+                */
+               shdr.sh_size = 0;
+
+               if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0)
+                       die("Seek to %d failed: %s\n",
+                           sec->shdr_offset, strerror(errno));
+
+               if (fwrite(&shdr, sizeof(shdr), 1, fp) != 1)
+                       die("Cannot write ELF section headers %d/%d: %s\n",
+                           i, ehdr.e_shnum, strerror(errno));
+       }
+}
+
+static void add_reloc(struct relocs *r, uint32_t offset, unsigned type)
+{
+       /* Relocation representation in binary table:
+        * |76543210|76543210|76543210|76543210|
+        * |  Type  |  offset from _text >> 2  |
+        */
+       offset >>= 2;
+       if (offset > 0x00FFFFFF)
+               die("Kernel image exceeds maximum size for relocation!\n");
+
+       offset = (offset & 0x00FFFFFF) | ((type & 0xFF) << 24);
+
+       if (r->count == r->size) {
+               unsigned long newsize = r->size + 50000;
+               void *mem = realloc(r->offset, newsize * sizeof(r->offset[0]));
+
+               if (!mem)
+                       die("realloc failed\n");
+
+               r->offset = mem;
+               r->size = newsize;
+       }
+       r->offset[r->count++] = offset;
+}
+
+static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel,
+                       Elf_Sym *sym, const char *symname))
+{
+       int i;
+
+       /* Walk through the relocations */
+       for (i = 0; i < ehdr.e_shnum; i++) {
+               char *sym_strtab;
+               Elf_Sym *sh_symtab;
+               struct section *sec_applies, *sec_symtab;
+               int j;
+               struct section *sec = &secs[i];
+
+               if (sec->shdr.sh_type != SHT_REL_TYPE)
+                       continue;
+
+               sec_symtab  = sec->link;
+               sec_applies = &secs[sec->shdr.sh_info];
+               if (!(sec_applies->shdr.sh_flags & SHF_ALLOC))
+                       continue;
+
+               sh_symtab = sec_symtab->symtab;
+               sym_strtab = sec_symtab->link->strtab;
+               for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+                       Elf_Rel *rel = &sec->reltab[j];
+                       Elf_Sym *sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
+                       const char *symname = sym_name(sym_strtab, sym);
+
+                       process(sec, rel, sym, symname);
+               }
+       }
+}
+
+static int do_reloc(struct section *sec, Elf_Rel *rel, Elf_Sym *sym,
+                     const char *symname)
+{
+       unsigned r_type = ELF_R_TYPE(rel->r_info);
+       unsigned bind = ELF_ST_BIND(sym->st_info);
+
+       if ((bind == STB_WEAK) && (sym->st_value == 0)) {
+               /* Don't relocate weak symbols without a target */
+               return 0;
+       }
+
+       if (regex_skip_reloc(symname))
+               return 0;
+
+       switch (r_type) {
+       case R_MIPS_NONE:
+       case R_MIPS_REL32:
+       case R_MIPS_PC16:
+       case R_MIPS_PC21_S2:
+       case R_MIPS_PC26_S2:
+               /*
+                * NONE can be ignored and PC relative relocations don't
+                * need to be adjusted.
+                */
+       case R_MIPS_HIGHEST:
+       case R_MIPS_HIGHER:
+               /* We support relocating within the same 4Gb segment only,
+                * thus leaving the top 32bits unchanged
+                */
+       case R_MIPS_LO16:
+               /* We support relocating by 64k jumps only
+                * thus leaving the bottom 16bits unchanged
+                */
+               break;
+
+       case R_MIPS_64:
+       case R_MIPS_32:
+       case R_MIPS_26:
+       case R_MIPS_HI16:
+               add_reloc(&relocs, rel->r_offset, r_type);
+               break;
+
+       default:
+               die("Unsupported relocation type: %s (%d)\n",
+                   rel_type(r_type), r_type);
+               break;
+       }
+
+       return 0;
+}
+
+static int write_reloc_as_bin(uint32_t v, FILE *f)
+{
+       unsigned char buf[4];
+
+       v = cpu_to_elf32(v);
+
+       memcpy(buf, &v, sizeof(uint32_t));
+       return fwrite(buf, 1, 4, f);
+}
+
+static int write_reloc_as_text(uint32_t v, FILE *f)
+{
+       int res;
+
+       res = fprintf(f, "\t.long 0x%08"PRIx32"\n", v);
+       if (res < 0)
+               return res;
+       else
+               return sizeof(uint32_t);
+}
+
+static void emit_relocs(int as_text, int as_bin, FILE *outf)
+{
+       int i;
+       int (*write_reloc)(uint32_t, FILE *) = write_reloc_as_bin;
+       int size = 0;
+       int size_reserved;
+       struct section *sec_reloc;
+
+       sec_reloc = sec_lookup(".data.reloc");
+       if (!sec_reloc)
+               die("Could not find relocation section\n");
+
+       size_reserved = sec_reloc->shdr.sh_size;
+
+       /* Collect up the relocations */
+       walk_relocs(do_reloc);
+
+       /* Print the relocations */
+       if (as_text) {
+               /* Print the relocations in a form suitable that
+                * gas will like.
+                */
+               printf(".section \".data.reloc\",\"a\"\n");
+               printf(".balign 4\n");
+               /* Output text to stdout */
+               write_reloc = write_reloc_as_text;
+               outf = stdout;
+       } else if (as_bin) {
+               /* Output raw binary to stdout */
+               outf = stdout;
+       } else {
+               /* Seek to offset of the relocation section.
+               * Each relocation is then written into the
+               * vmlinux kernel image.
+               */
+               if (fseek(outf, sec_reloc->shdr.sh_offset, SEEK_SET) < 0) {
+                       die("Seek to %d failed: %s\n",
+                               sec_reloc->shdr.sh_offset, strerror(errno));
+               }
+       }
+
+       for (i = 0; i < relocs.count; i++)
+               size += write_reloc(relocs.offset[i], outf);
+
+       /* Print a stop, but only if we've actually written some relocs */
+       if (size)
+               size += write_reloc(0, outf);
+
+       if (size > size_reserved)
+               /* Die, but suggest a value for CONFIG_RELOCATION_TABLE_SIZE
+                * which will fix this problem and allow a bit of headroom
+                * if more kernel features are enabled
+                */
+               die("Relocations overflow available space!\n" \
+                   "Please adjust CONFIG_RELOCATION_TABLE_SIZE " \
+                   "to at least 0x%08x\n", (size + 0x1000) & ~0xFFF);
+}
+
+/*
+ * As an aid to debugging problems with different linkers
+ * print summary information about the relocs.
+ * Since different linkers tend to emit the sections in
+ * different orders we use the section names in the output.
+ */
+static int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
+                               const char *symname)
+{
+       printf("%16s  0x%08x  %16s  %40s  %16s\n",
+               sec_name(sec->shdr.sh_info),
+               (unsigned int)rel->r_offset,
+               rel_type(ELF_R_TYPE(rel->r_info)),
+               symname,
+               sec_name(sym->st_shndx));
+       return 0;
+}
+
+static void print_reloc_info(void)
+{
+       printf("%16s  %10s  %16s  %40s  %16s\n",
+               "reloc section",
+               "offset",
+               "reloc type",
+               "symbol",
+               "symbol section");
+       walk_relocs(do_reloc_info);
+}
+
+#if ELF_BITS == 64
+# define process process_64
+#else
+# define process process_32
+#endif
+
+void process(FILE *fp, int as_text, int as_bin,
+            int show_reloc_info, int keep_relocs)
+{
+       regex_init();
+       read_ehdr(fp);
+       read_shdrs(fp);
+       read_strtabs(fp);
+       read_symtabs(fp);
+       read_relocs(fp);
+       if (show_reloc_info) {
+               print_reloc_info();
+               return;
+       }
+       emit_relocs(as_text, as_bin, fp);
+       if (!keep_relocs)
+               remove_relocs(fp);
+}
diff --git a/arch/mips/boot/tools/relocs.h b/arch/mips/boot/tools/relocs.h
new file mode 100644 (file)
index 0000000..3cf676f
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef RELOCS_H
+#define RELOCS_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <elf.h>
+#include <byteswap.h>
+#define USE_BSD
+#include <endian.h>
+#include <regex.h>
+
+void die(char *fmt, ...);
+
+/*
+ * Introduced for MIPSr6
+ */
+#ifndef R_MIPS_PC21_S2
+#define R_MIPS_PC21_S2         60
+#endif
+
+#ifndef R_MIPS_PC26_S2
+#define R_MIPS_PC26_S2         61
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+enum symtype {
+       S_ABS,
+       S_REL,
+       S_SEG,
+       S_LIN,
+       S_NSYMTYPES
+};
+
+void process_32(FILE *fp, int as_text, int as_bin,
+               int show_reloc_info, int keep_relocs);
+void process_64(FILE *fp, int as_text, int as_bin,
+               int show_reloc_info, int keep_relocs);
+#endif /* RELOCS_H */
diff --git a/arch/mips/boot/tools/relocs_32.c b/arch/mips/boot/tools/relocs_32.c
new file mode 100644 (file)
index 0000000..915bdc0
--- /dev/null
@@ -0,0 +1,17 @@
+#include "relocs.h"
+
+#define ELF_BITS 32
+
+#define ELF_MACHINE            EM_MIPS
+#define ELF_MACHINE_NAME       "MIPS"
+#define SHT_REL_TYPE           SHT_REL
+#define Elf_Rel                        ElfW(Rel)
+
+#define ELF_CLASS              ELFCLASS32
+#define ELF_R_SYM(val)         ELF32_R_SYM(val)
+#define ELF_R_TYPE(val)                ELF32_R_TYPE(val)
+#define ELF_ST_TYPE(o)         ELF32_ST_TYPE(o)
+#define ELF_ST_BIND(o)         ELF32_ST_BIND(o)
+#define ELF_ST_VISIBILITY(o)   ELF32_ST_VISIBILITY(o)
+
+#include "relocs.c"
diff --git a/arch/mips/boot/tools/relocs_64.c b/arch/mips/boot/tools/relocs_64.c
new file mode 100644 (file)
index 0000000..b671b5e
--- /dev/null
@@ -0,0 +1,27 @@
+#include "relocs.h"
+
+#define ELF_BITS 64
+
+#define ELF_MACHINE             EM_MIPS
+#define ELF_MACHINE_NAME        "MIPS64"
+#define SHT_REL_TYPE            SHT_RELA
+#define Elf_Rel                 Elf64_Rela
+
+typedef uint8_t Elf64_Byte;
+
+typedef struct {
+       Elf64_Word r_sym;       /* Symbol index.  */
+       Elf64_Byte r_ssym;      /* Special symbol.  */
+       Elf64_Byte r_type3;     /* Third relocation.  */
+       Elf64_Byte r_type2;     /* Second relocation.  */
+       Elf64_Byte r_type;      /* First relocation.  */
+} Elf64_Mips_Rela;
+
+#define ELF_CLASS               ELFCLASS64
+#define ELF_R_SYM(val)          (((Elf64_Mips_Rela *)(&val))->r_sym)
+#define ELF_R_TYPE(val)         (((Elf64_Mips_Rela *)(&val))->r_type)
+#define ELF_ST_TYPE(o)          ELF64_ST_TYPE(o)
+#define ELF_ST_BIND(o)          ELF64_ST_BIND(o)
+#define ELF_ST_VISIBILITY(o)    ELF64_ST_VISIBILITY(o)
+
+#include "relocs.c"
diff --git a/arch/mips/boot/tools/relocs_main.c b/arch/mips/boot/tools/relocs_main.c
new file mode 100644 (file)
index 0000000..d8fe234
--- /dev/null
@@ -0,0 +1,84 @@
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <endian.h>
+#include <elf.h>
+
+#include "relocs.h"
+
+void die(char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       exit(1);
+}
+
+static void usage(void)
+{
+       die("relocs [--reloc-info|--text|--bin|--keep] vmlinux\n");
+}
+
+int main(int argc, char **argv)
+{
+       int show_reloc_info, as_text, as_bin, keep_relocs;
+       const char *fname;
+       FILE *fp;
+       int i;
+       unsigned char e_ident[EI_NIDENT];
+
+       show_reloc_info = 0;
+       as_text = 0;
+       as_bin = 0;
+       keep_relocs = 0;
+       fname = NULL;
+       for (i = 1; i < argc; i++) {
+               char *arg = argv[i];
+
+               if (*arg == '-') {
+                       if (strcmp(arg, "--reloc-info") == 0) {
+                               show_reloc_info = 1;
+                               continue;
+                       }
+                       if (strcmp(arg, "--text") == 0) {
+                               as_text = 1;
+                               continue;
+                       }
+                       if (strcmp(arg, "--bin") == 0) {
+                               as_bin = 1;
+                               continue;
+                       }
+                       if (strcmp(arg, "--keep") == 0) {
+                               keep_relocs = 1;
+                               continue;
+                       }
+               } else if (!fname) {
+                       fname = arg;
+                       continue;
+               }
+               usage();
+       }
+       if (!fname)
+               usage();
+
+       fp = fopen(fname, "r+");
+       if (!fp)
+               die("Cannot open %s: %s\n", fname, strerror(errno));
+
+       if (fread(&e_ident, 1, EI_NIDENT, fp) != EI_NIDENT)
+               die("Cannot read %s: %s", fname, strerror(errno));
+
+       rewind(fp);
+       if (e_ident[EI_CLASS] == ELFCLASS64)
+               process_64(fp, as_text,  as_bin, show_reloc_info, keep_relocs);
+       else
+               process_32(fp, as_text, as_bin, show_reloc_info, keep_relocs);
+       fclose(fp);
+       return 0;
+}
index 1882e6475dd093d546c70cf9f7345f8121589921..23c2344a35525fa9a0badfb3bbca9a89d60293c5 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/octeon/cvmx-ipd-defs.h>
 #include <asm/octeon/cvmx-mio-defs.h>
 #include <asm/octeon/cvmx-rst-defs.h>
+#include <asm/octeon/cvmx-fpa-defs.h>
 
 static u64 f;
 static u64 rdiv;
@@ -65,9 +66,13 @@ void __init octeon_setup_delays(void)
  */
 void octeon_init_cvmcount(void)
 {
+       u64 clk_reg;
        unsigned long flags;
        unsigned loops = 2;
 
+       clk_reg = octeon_has_feature(OCTEON_FEATURE_FPA3) ?
+               CVMX_FPA_CLK_COUNT : CVMX_IPD_CLK_COUNT;
+
        /* Clobber loops so GCC will not unroll the following while loop. */
        asm("" : "+r" (loops));
 
@@ -77,18 +82,18 @@ void octeon_init_cvmcount(void)
         * which should give more deterministic timing.
         */
        while (loops--) {
-               u64 ipd_clk_count = cvmx_read_csr(CVMX_IPD_CLK_COUNT);
+               u64 clk_count = cvmx_read_csr(clk_reg);
                if (rdiv != 0) {
-                       ipd_clk_count *= rdiv;
+                       clk_count *= rdiv;
                        if (f != 0) {
                                asm("dmultu\t%[cnt],%[f]\n\t"
                                    "mfhi\t%[cnt]"
-                                   : [cnt] "+r" (ipd_clk_count)
+                                   : [cnt] "+r" (clk_count)
                                    : [f] "r" (f)
                                    : "hi", "lo");
                        }
                }
-               write_c0_cvmcount(ipd_clk_count);
+               write_c0_cvmcount(clk_count);
        }
        local_irq_restore(flags);
 }
index 376701f41cc28eb6a78f227836b105af843a794b..ff26d0217b878feb1aca373c588337af96af8431 100644 (file)
@@ -87,6 +87,8 @@ int cvmx_helper_get_number_of_interfaces(void)
                return 9;
        if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
                return 4;
+       if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
+               return 5;
        else
                return 3;
 }
@@ -259,6 +261,41 @@ static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
        }
 }
 
+/**
+ * @INTERNAL
+ * Return interface mode for CN7XXX.
+ */
+static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
+{
+       union cvmx_gmxx_inf_mode mode;
+
+       mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
+
+       switch (interface) {
+       case 0:
+       case 1:
+               switch (mode.cn68xx.mode) {
+               case 0:
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+               case 1:
+               case 2:
+                       return CVMX_HELPER_INTERFACE_MODE_SGMII;
+               case 3:
+                       return CVMX_HELPER_INTERFACE_MODE_XAUI;
+               default:
+                       return CVMX_HELPER_INTERFACE_MODE_SGMII;
+               }
+       case 2:
+               return CVMX_HELPER_INTERFACE_MODE_NPI;
+       case 3:
+               return CVMX_HELPER_INTERFACE_MODE_LOOP;
+       case 4:
+               return CVMX_HELPER_INTERFACE_MODE_RGMII;
+       default:
+               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+       }
+}
+
 /**
  * Get the operating mode of an interface. Depending on the Octeon
  * chip and configuration, this function returns an enumeration
@@ -277,6 +314,12 @@ cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
            interface >= cvmx_helper_get_number_of_interfaces())
                return CVMX_HELPER_INTERFACE_MODE_DISABLED;
 
+       /*
+        * OCTEON III models
+        */
+       if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
+               return __cvmx_get_mode_cn7xxx(interface);
+
        /*
         * Octeon II models
         */
index 3d17fac293597a2b53bb9e9db19e679807423f89..cc1b1d2a6fa1567e7030da90ab71f476af724e18 100644 (file)
 #include <linux/module.h>
 
 #include <asm/octeon/cvmx.h>
-#include <asm/octeon/cvmx-spinlock.h>
 #include <asm/octeon/cvmx-sysinfo.h>
 
-/**
+/*
  * This structure defines the private state maintained by sysinfo module.
- *
  */
-static struct {
-       struct cvmx_sysinfo sysinfo;       /* system information */
-       cvmx_spinlock_t lock;      /* mutex spinlock */
-
-} state = {
-       .lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER
-};
-
+static struct cvmx_sysinfo sysinfo;       /* system information */
 
 /*
- * Global variables that define the min/max of the memory region set
- * up for 32 bit userspace access.
- */
-uint64_t linux_mem32_min;
-uint64_t linux_mem32_max;
-uint64_t linux_mem32_wired;
-uint64_t linux_mem32_offset;
-
-/**
- * This function returns the application information as obtained
+ * Returns the application information as obtained
  * by the bootloader.  This provides the core mask of the cores
  * running the same application image, as well as the physical
  * memory regions available to the core.
- *
- * Returns  Pointer to the boot information structure
- *
  */
 struct cvmx_sysinfo *cvmx_sysinfo_get(void)
 {
-       return &(state.sysinfo);
+       return &sysinfo;
 }
 EXPORT_SYMBOL(cvmx_sysinfo_get);
 
-/**
- * This function is used in non-simple executive environments (such as
- * Linux kernel, u-boot, etc.) to configure the minimal fields that
- * are required to use simple executive files directly.
- *
- * Locking (if required) must be handled outside of this
- * function
- *
- * @phy_mem_desc_ptr:
- *                  Pointer to global physical memory descriptor
- *                  (bootmem descriptor) @board_type: Octeon board
- *                  type enumeration
- *
- * @board_rev_major:
- *                  Board major revision
- * @board_rev_minor:
- *                  Board minor revision
- * @cpu_clock_hz:
- *                  CPU clock freqency in hertz
- *
- * Returns 0: Failure
- *        1: success
- */
-int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr,
-                                   uint16_t board_type,
-                                   uint8_t board_rev_major,
-                                   uint8_t board_rev_minor,
-                                   uint32_t cpu_clock_hz)
-{
-
-       /* The sysinfo structure was already initialized */
-       if (state.sysinfo.board_type)
-               return 0;
-
-       memset(&(state.sysinfo), 0x0, sizeof(state.sysinfo));
-       state.sysinfo.phy_mem_desc_ptr = phy_mem_desc_ptr;
-       state.sysinfo.board_type = board_type;
-       state.sysinfo.board_rev_major = board_rev_major;
-       state.sysinfo.board_rev_minor = board_rev_minor;
-       state.sysinfo.cpu_clock_hz = cpu_clock_hz;
-
-       return 1;
-}
index b2104bd9ab3b7ef08a998253661b59cb7f914df4..d08a2bce653cf235cd280c3d499ddce5f64d0b48 100644 (file)
@@ -71,11 +71,11 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
        uint32_t fuse_data = 0;
 
        fus3.u64 = 0;
-       if (!OCTEON_IS_MODEL(OCTEON_CN6XXX))
+       if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
                fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
        fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
        fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
-       num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE));
+       num_cores = cvmx_octeon_num_cores();
 
        /* Make sure the non existent devices look disabled */
        switch ((chip_id >> 8) & 0xff) {
@@ -121,6 +121,15 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
         * later.
         */
        switch (num_cores) {
+       case 48:
+               core_model = "90";
+               break;
+       case 44:
+               core_model = "88";
+               break;
+       case 40:
+               core_model = "85";
+               break;
        case 32:
                core_model = "80";
                break;
@@ -297,7 +306,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
                                if (fus_dat3.s.nozip)
                                        suffix = "SCP";
 
-                               if (fus_dat3.s.bar2_en)
+                               if (fus_dat3.cn56xx.bar2_en)
                                        suffix = "NSPB2";
                        }
                        if (fus3.cn56xx.crip_1024k)
@@ -369,6 +378,73 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
                else
                        suffix = "AAP";
                break;
+       case 0x94:              /* CNF71XX */
+               family = "F71";
+               if (fus_dat3.cnf71xx.nozip)
+                       suffix = "SCP";
+               else
+                       suffix = "AAP";
+               break;
+       case 0x95:              /* CN78XX */
+               if (num_cores == 6)     /* Other core counts match generic */
+                       core_model = "35";
+               if (OCTEON_IS_MODEL(OCTEON_CN76XX))
+                       family = "76";
+               else
+                       family = "78";
+               if (fus_dat3.cn78xx.l2c_crip == 2)
+                       family = "77";
+               if (fus_dat3.cn78xx.nozip
+                   && fus_dat3.cn78xx.nodfa_dte
+                   && fus_dat3.cn78xx.nohna_dte) {
+                       if (fus_dat3.cn78xx.nozip &&
+                               !fus_dat2.cn78xx.raid_en &&
+                               fus_dat3.cn78xx.nohna_dte) {
+                               suffix = "CP";
+                       } else {
+                               suffix = "SCP";
+                       }
+               } else if (fus_dat2.cn78xx.raid_en == 0)
+                       suffix = "HCP";
+               else
+                       suffix = "AAP";
+               break;
+       case 0x96:              /* CN70XX */
+               family = "70";
+               if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32))
+                       family = "71";
+               if (fus_dat2.cn70xx.nocrypto)
+                       suffix = "CP";
+               else if (fus_dat3.cn70xx.nodfa_dte)
+                       suffix = "SCP";
+               else
+                       suffix = "AAP";
+               break;
+       case 0x97:              /* CN73XX */
+               if (num_cores == 6)     /* Other core counts match generic */
+                       core_model = "35";
+               family = "73";
+               if (fus_dat3.cn73xx.l2c_crip == 2)
+                       family = "72";
+               if (fus_dat3.cn73xx.nozip
+                               && fus_dat3.cn73xx.nodfa_dte
+                               && fus_dat3.cn73xx.nohna_dte) {
+                       if (!fus_dat2.cn73xx.raid_en)
+                               suffix = "CP";
+                       else
+                               suffix = "SCP";
+               } else
+                       suffix = "AAP";
+               break;
+       case 0x98:              /* CN75XX */
+               family = "F75";
+               if (fus_dat3.cn78xx.nozip
+                   && fus_dat3.cn78xx.nodfa_dte
+                   && fus_dat3.cn78xx.nohna_dte)
+                       suffix = "SCP";
+               else
+                       suffix = "AAP";
+               break;
        default:
                family = "XX";
                core_model = "XX";
index 4f9eb05768840f93006384959f0a7dfffdb7caf2..368eb490354ced34c29a3e0b640ac66c9762b977 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2014 Cavium, Inc.
+ * Copyright (C) 2004-2016 Cavium, Inc.
  */
 
 #include <linux/of_address.h>
 
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-ciu2-defs.h>
+#include <asm/octeon/cvmx-ciu3-defs.h>
 
 static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror);
 static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror);
 static DEFINE_PER_CPU(raw_spinlock_t, octeon_irq_ciu_spinlock);
+static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip2);
+
+static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip3);
+static DEFINE_PER_CPU(struct octeon_ciu3_info *, octeon_ciu3_info);
+#define CIU3_MBOX_PER_CORE 10
+
+/*
+ * The 8 most significant bits of the intsn identify the interrupt major block.
+ * Each major block might use its own interrupt domain. Thus 256 domains are
+ * needed.
+ */
+#define MAX_CIU3_DOMAINS               256
+
+typedef irq_hw_number_t (*octeon_ciu3_intsn2hw_t)(struct irq_domain *, unsigned int);
+
+/* Information for each ciu3 in the system */
+struct octeon_ciu3_info {
+       u64                     ciu3_addr;
+       int                     node;
+       struct irq_domain       *domain[MAX_CIU3_DOMAINS];
+       octeon_ciu3_intsn2hw_t  intsn2hw[MAX_CIU3_DOMAINS];
+};
+
+/* Each ciu3 in the system uses its own data (one ciu3 per node) */
+static struct octeon_ciu3_info *octeon_ciu3_info_per_node[4];
 
 struct octeon_irq_ciu_domain_data {
        int num_sum;  /* number of sum registers (2 or 3). */
 };
 
-static __read_mostly u8 octeon_irq_ciu_to_irq[8][64];
+/* Register offsets from ciu3_addr */
+#define CIU3_CONST             0x220
+#define CIU3_IDT_CTL(_idt)     ((_idt) * 8 + 0x110000)
+#define CIU3_IDT_PP(_idt, _idx)        ((_idt) * 32 + (_idx) * 8 + 0x120000)
+#define CIU3_IDT_IO(_idt)      ((_idt) * 8 + 0x130000)
+#define CIU3_DEST_PP_INT(_pp_ip) ((_pp_ip) * 8 + 0x200000)
+#define CIU3_DEST_IO_INT(_io)  ((_io) * 8 + 0x210000)
+#define CIU3_ISC_CTL(_intsn)   ((_intsn) * 8 + 0x80000000)
+#define CIU3_ISC_W1C(_intsn)   ((_intsn) * 8 + 0x90000000)
+#define CIU3_ISC_W1S(_intsn)   ((_intsn) * 8 + 0xa0000000)
+
+static __read_mostly int octeon_irq_ciu_to_irq[8][64];
 
 struct octeon_ciu_chip_data {
        union {
@@ -39,10 +76,11 @@ struct octeon_ciu_chip_data {
                struct {                /* only used for ciu/ciu2 */
                        u8 line;
                        u8 bit;
-                       u8 gpio_line;
                };
        };
+       int gpio_line;
        int current_cpu;        /* Next CPU expected to take this irq */
+       int ciu_node; /* NUMA node number of the CIU */
 };
 
 struct octeon_core_chip_data {
@@ -626,6 +664,18 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data)
        }
 }
 
+static int octeon_irq_ciu_set_type(struct irq_data *data, unsigned int t)
+{
+       irqd_set_trigger_type(data, t);
+
+       if (t & IRQ_TYPE_EDGE_BOTH)
+               irq_set_handler_locked(data, handle_edge_irq);
+       else
+               irq_set_handler_locked(data, handle_level_irq);
+
+       return IRQ_SET_MASK_OK;
+}
+
 static void octeon_irq_gpio_setup(struct irq_data *data)
 {
        union cvmx_gpio_bit_cfgx cfg;
@@ -663,7 +713,7 @@ static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t)
        irqd_set_trigger_type(data, t);
        octeon_irq_gpio_setup(data);
 
-       if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
+       if (t & IRQ_TYPE_EDGE_BOTH)
                irq_set_handler_locked(data, handle_edge_irq);
        else
                irq_set_handler_locked(data, handle_level_irq);
@@ -863,6 +913,16 @@ static int octeon_irq_ciu_set_affinity_sum2(struct irq_data *data,
 }
 #endif
 
+static unsigned int edge_startup(struct irq_data *data)
+{
+       /* ack any pending edge-irq at startup, so there is
+        * an _edge_ to fire on when the event reappears.
+        */
+       data->chip->irq_ack(data);
+       data->chip->irq_enable(data);
+       return 0;
+}
+
 /*
  * Newer octeon chips have support for lockless CIU operation.
  */
@@ -1158,16 +1218,6 @@ static struct irq_chip *octeon_irq_ciu_chip;
 static struct irq_chip *octeon_irq_ciu_chip_edge;
 static struct irq_chip *octeon_irq_gpio_chip;
 
-static bool octeon_irq_virq_in_range(unsigned int virq)
-{
-       /* We cannot let it overflow the mapping array. */
-       if (virq < (1ul << 8 * sizeof(octeon_irq_ciu_to_irq[0][0])))
-               return true;
-
-       WARN_ONCE(true, "virq out of range %u.\n", virq);
-       return false;
-}
-
 static int octeon_irq_ciu_map(struct irq_domain *d,
                              unsigned int virq, irq_hw_number_t hw)
 {
@@ -1176,13 +1226,6 @@ static int octeon_irq_ciu_map(struct irq_domain *d,
        unsigned int bit = hw & 63;
        struct octeon_irq_ciu_domain_data *dd = d->host_data;
 
-       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 >= dd->num_sum || octeon_irq_ciu_to_irq[line][bit] != 0)
                return -EINVAL;
 
@@ -1215,9 +1258,6 @@ static int octeon_irq_gpio_map(struct irq_domain *d,
        unsigned int line, bit;
        int r;
 
-       if (!octeon_irq_virq_in_range(virq))
-               return -EINVAL;
-
        line = (hw + gpiod->base_hwirq) >> 6;
        bit = (hw + gpiod->base_hwirq) & 63;
        if (line > ARRAY_SIZE(octeon_irq_ciu_to_irq) ||
@@ -1899,9 +1939,6 @@ static int octeon_irq_ciu2_map(struct irq_domain *d,
        unsigned int line = hw >> 6;
        unsigned int bit = hw & 63;
 
-       if (!octeon_irq_virq_in_range(virq))
-               return -EINVAL;
-
        /*
         * Don't map irq if it is reserved for GPIO.
         * (Line 7 are the GPIO lines.)
@@ -2294,10 +2331,598 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node,
        return 0;
 }
 
+int octeon_irq_ciu3_xlat(struct irq_domain *d,
+                        struct device_node *node,
+                        const u32 *intspec,
+                        unsigned int intsize,
+                        unsigned long *out_hwirq,
+                        unsigned int *out_type)
+{
+       struct octeon_ciu3_info *ciu3_info = d->host_data;
+       unsigned int hwirq, type, intsn_major;
+       union cvmx_ciu3_iscx_ctl isc;
+
+       if (intsize < 2)
+               return -EINVAL;
+       hwirq = intspec[0];
+       type = intspec[1];
+
+       if (hwirq >= (1 << 20))
+               return -EINVAL;
+
+       intsn_major = hwirq >> 12;
+       switch (intsn_major) {
+       case 0x04: /* Software handled separately. */
+               return -EINVAL;
+       default:
+               break;
+       }
+
+       isc.u64 =  cvmx_read_csr(ciu3_info->ciu3_addr + CIU3_ISC_CTL(hwirq));
+       if (!isc.s.imp)
+               return -EINVAL;
+
+       switch (type) {
+       case 4: /* official value for level triggering. */
+               *out_type = IRQ_TYPE_LEVEL_HIGH;
+               break;
+       case 0: /* unofficial value, but we might as well let it work. */
+       case 1: /* official value for edge triggering. */
+               *out_type = IRQ_TYPE_EDGE_RISING;
+               break;
+       default: /* Nothing else is acceptable. */
+               return -EINVAL;
+       }
+
+       *out_hwirq = hwirq;
+
+       return 0;
+}
+
+void octeon_irq_ciu3_enable(struct irq_data *data)
+{
+       int cpu;
+       union cvmx_ciu3_iscx_ctl isc_ctl;
+       union cvmx_ciu3_iscx_w1c isc_w1c;
+       u64 isc_ctl_addr;
+
+       struct octeon_ciu_chip_data *cd;
+
+       cpu = next_cpu_for_irq(data);
+
+       cd = irq_data_get_irq_chip_data(data);
+
+       isc_w1c.u64 = 0;
+       isc_w1c.s.en = 1;
+       cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64);
+
+       isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn);
+       isc_ctl.u64 = 0;
+       isc_ctl.s.en = 1;
+       isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu);
+       cvmx_write_csr(isc_ctl_addr, isc_ctl.u64);
+       cvmx_read_csr(isc_ctl_addr);
+}
+
+void octeon_irq_ciu3_disable(struct irq_data *data)
+{
+       u64 isc_ctl_addr;
+       union cvmx_ciu3_iscx_w1c isc_w1c;
+
+       struct octeon_ciu_chip_data *cd;
+
+       cd = irq_data_get_irq_chip_data(data);
+
+       isc_w1c.u64 = 0;
+       isc_w1c.s.en = 1;
+
+       isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn);
+       cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64);
+       cvmx_write_csr(isc_ctl_addr, 0);
+       cvmx_read_csr(isc_ctl_addr);
+}
+
+void octeon_irq_ciu3_ack(struct irq_data *data)
+{
+       u64 isc_w1c_addr;
+       union cvmx_ciu3_iscx_w1c isc_w1c;
+       struct octeon_ciu_chip_data *cd;
+       u32 trigger_type = irqd_get_trigger_type(data);
+
+       /*
+        * We use a single irq_chip, so we have to do nothing to ack a
+        * level interrupt.
+        */
+       if (!(trigger_type & IRQ_TYPE_EDGE_BOTH))
+               return;
+
+       cd = irq_data_get_irq_chip_data(data);
+
+       isc_w1c.u64 = 0;
+       isc_w1c.s.raw = 1;
+
+       isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn);
+       cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+       cvmx_read_csr(isc_w1c_addr);
+}
+
+void octeon_irq_ciu3_mask(struct irq_data *data)
+{
+       union cvmx_ciu3_iscx_w1c isc_w1c;
+       u64 isc_w1c_addr;
+       struct octeon_ciu_chip_data *cd;
+
+       cd = irq_data_get_irq_chip_data(data);
+
+       isc_w1c.u64 = 0;
+       isc_w1c.s.en = 1;
+
+       isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn);
+       cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+       cvmx_read_csr(isc_w1c_addr);
+}
+
+void octeon_irq_ciu3_mask_ack(struct irq_data *data)
+{
+       union cvmx_ciu3_iscx_w1c isc_w1c;
+       u64 isc_w1c_addr;
+       struct octeon_ciu_chip_data *cd;
+       u32 trigger_type = irqd_get_trigger_type(data);
+
+       cd = irq_data_get_irq_chip_data(data);
+
+       isc_w1c.u64 = 0;
+       isc_w1c.s.en = 1;
+
+       /*
+        * We use a single irq_chip, so only ack an edge (!level)
+        * interrupt.
+        */
+       if (trigger_type & IRQ_TYPE_EDGE_BOTH)
+               isc_w1c.s.raw = 1;
+
+       isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn);
+       cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+       cvmx_read_csr(isc_w1c_addr);
+}
+
+#ifdef CONFIG_SMP
+int octeon_irq_ciu3_set_affinity(struct irq_data *data,
+                                const struct cpumask *dest, bool force)
+{
+       union cvmx_ciu3_iscx_ctl isc_ctl;
+       union cvmx_ciu3_iscx_w1c isc_w1c;
+       u64 isc_ctl_addr;
+       int cpu;
+       bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
+       struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data);
+
+       if (!cpumask_subset(dest, cpumask_of_node(cd->ciu_node)))
+               return -EINVAL;
+
+       if (!enable_one)
+               return IRQ_SET_MASK_OK;
+
+       cd = irq_data_get_irq_chip_data(data);
+       cpu = cpumask_first(dest);
+       if (cpu >= nr_cpu_ids)
+               cpu = smp_processor_id();
+       cd->current_cpu = cpu;
+
+       isc_w1c.u64 = 0;
+       isc_w1c.s.en = 1;
+       cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64);
+
+       isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn);
+       isc_ctl.u64 = 0;
+       isc_ctl.s.en = 1;
+       isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu);
+       cvmx_write_csr(isc_ctl_addr, isc_ctl.u64);
+       cvmx_read_csr(isc_ctl_addr);
+
+       return IRQ_SET_MASK_OK;
+}
+#endif
+
+static struct irq_chip octeon_irq_chip_ciu3 = {
+       .name = "CIU3",
+       .irq_startup = edge_startup,
+       .irq_enable = octeon_irq_ciu3_enable,
+       .irq_disable = octeon_irq_ciu3_disable,
+       .irq_ack = octeon_irq_ciu3_ack,
+       .irq_mask = octeon_irq_ciu3_mask,
+       .irq_mask_ack = octeon_irq_ciu3_mask_ack,
+       .irq_unmask = octeon_irq_ciu3_enable,
+       .irq_set_type = octeon_irq_ciu_set_type,
+#ifdef CONFIG_SMP
+       .irq_set_affinity = octeon_irq_ciu3_set_affinity,
+       .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
+#endif
+};
+
+int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq,
+                        irq_hw_number_t hw, struct irq_chip *chip)
+{
+       struct octeon_ciu3_info *ciu3_info = d->host_data;
+       struct octeon_ciu_chip_data *cd = kzalloc_node(sizeof(*cd), GFP_KERNEL,
+                                                      ciu3_info->node);
+       if (!cd)
+               return -ENOMEM;
+       cd->intsn = hw;
+       cd->current_cpu = -1;
+       cd->ciu3_addr = ciu3_info->ciu3_addr;
+       cd->ciu_node = ciu3_info->node;
+       irq_set_chip_and_handler(virq, chip, handle_edge_irq);
+       irq_set_chip_data(virq, cd);
+
+       return 0;
+}
+
+static int octeon_irq_ciu3_map(struct irq_domain *d,
+                              unsigned int virq, irq_hw_number_t hw)
+{
+       return octeon_irq_ciu3_mapx(d, virq, hw, &octeon_irq_chip_ciu3);
+}
+
+static struct irq_domain_ops octeon_dflt_domain_ciu3_ops = {
+       .map = octeon_irq_ciu3_map,
+       .unmap = octeon_irq_free_cd,
+       .xlate = octeon_irq_ciu3_xlat,
+};
+
+static void octeon_irq_ciu3_ip2(void)
+{
+       union cvmx_ciu3_destx_pp_int dest_pp_int;
+       struct octeon_ciu3_info *ciu3_info;
+       u64 ciu3_addr;
+
+       ciu3_info = __this_cpu_read(octeon_ciu3_info);
+       ciu3_addr = ciu3_info->ciu3_addr;
+
+       dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(3 * cvmx_get_local_core_num()));
+
+       if (likely(dest_pp_int.s.intr)) {
+               irq_hw_number_t intsn = dest_pp_int.s.intsn;
+               irq_hw_number_t hw;
+               struct irq_domain *domain;
+               /* Get the domain to use from the major block */
+               int block = intsn >> 12;
+               int ret;
+
+               domain = ciu3_info->domain[block];
+               if (ciu3_info->intsn2hw[block])
+                       hw = ciu3_info->intsn2hw[block](domain, intsn);
+               else
+                       hw = intsn;
+
+               ret = handle_domain_irq(domain, hw, NULL);
+               if (ret < 0) {
+                       union cvmx_ciu3_iscx_w1c isc_w1c;
+                       u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn);
+
+                       isc_w1c.u64 = 0;
+                       isc_w1c.s.en = 1;
+                       cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+                       cvmx_read_csr(isc_w1c_addr);
+                       spurious_interrupt();
+               }
+       } else {
+               spurious_interrupt();
+       }
+}
+
+/*
+ * 10 mbox per core starting from zero.
+ * Base mbox is core * 10
+ */
+static unsigned int octeon_irq_ciu3_base_mbox_intsn(int core)
+{
+       /* SW (mbox) are 0x04 in bits 12..19 */
+       return 0x04000 + CIU3_MBOX_PER_CORE * core;
+}
+
+static unsigned int octeon_irq_ciu3_mbox_intsn_for_core(int core, unsigned int mbox)
+{
+       return octeon_irq_ciu3_base_mbox_intsn(core) + mbox;
+}
+
+static unsigned int octeon_irq_ciu3_mbox_intsn_for_cpu(int cpu, unsigned int mbox)
+{
+       int local_core = octeon_coreid_for_cpu(cpu) & 0x3f;
+
+       return octeon_irq_ciu3_mbox_intsn_for_core(local_core, mbox);
+}
+
+static void octeon_irq_ciu3_mbox(void)
+{
+       union cvmx_ciu3_destx_pp_int dest_pp_int;
+       struct octeon_ciu3_info *ciu3_info;
+       u64 ciu3_addr;
+       int core = cvmx_get_local_core_num();
+
+       ciu3_info = __this_cpu_read(octeon_ciu3_info);
+       ciu3_addr = ciu3_info->ciu3_addr;
+
+       dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(1 + 3 * core));
+
+       if (likely(dest_pp_int.s.intr)) {
+               irq_hw_number_t intsn = dest_pp_int.s.intsn;
+               int mbox = intsn - octeon_irq_ciu3_base_mbox_intsn(core);
+
+               if (likely(mbox >= 0 && mbox < CIU3_MBOX_PER_CORE)) {
+                       do_IRQ(mbox + OCTEON_IRQ_MBOX0);
+               } else {
+                       union cvmx_ciu3_iscx_w1c isc_w1c;
+                       u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn);
+
+                       isc_w1c.u64 = 0;
+                       isc_w1c.s.en = 1;
+                       cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+                       cvmx_read_csr(isc_w1c_addr);
+                       spurious_interrupt();
+               }
+       } else {
+               spurious_interrupt();
+       }
+}
+
+void octeon_ciu3_mbox_send(int cpu, unsigned int mbox)
+{
+       struct octeon_ciu3_info *ciu3_info;
+       unsigned int intsn;
+       union cvmx_ciu3_iscx_w1s isc_w1s;
+       u64 isc_w1s_addr;
+
+       if (WARN_ON_ONCE(mbox >= CIU3_MBOX_PER_CORE))
+               return;
+
+       intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox);
+       ciu3_info = per_cpu(octeon_ciu3_info, cpu);
+       isc_w1s_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1S(intsn);
+
+       isc_w1s.u64 = 0;
+       isc_w1s.s.raw = 1;
+
+       cvmx_write_csr(isc_w1s_addr, isc_w1s.u64);
+       cvmx_read_csr(isc_w1s_addr);
+}
+
+static void octeon_irq_ciu3_mbox_set_enable(struct irq_data *data, int cpu, bool en)
+{
+       struct octeon_ciu3_info *ciu3_info;
+       unsigned int intsn;
+       u64 isc_ctl_addr, isc_w1c_addr;
+       union cvmx_ciu3_iscx_ctl isc_ctl;
+       unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+       intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox);
+       ciu3_info = per_cpu(octeon_ciu3_info, cpu);
+       isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn);
+       isc_ctl_addr = ciu3_info->ciu3_addr + CIU3_ISC_CTL(intsn);
+
+       isc_ctl.u64 = 0;
+       isc_ctl.s.en = 1;
+
+       cvmx_write_csr(isc_w1c_addr, isc_ctl.u64);
+       cvmx_write_csr(isc_ctl_addr, 0);
+       if (en) {
+               unsigned int idt = per_cpu(octeon_irq_ciu3_idt_ip3, cpu);
+
+               isc_ctl.u64 = 0;
+               isc_ctl.s.en = 1;
+               isc_ctl.s.idt = idt;
+               cvmx_write_csr(isc_ctl_addr, isc_ctl.u64);
+       }
+       cvmx_read_csr(isc_ctl_addr);
+}
+
+static void octeon_irq_ciu3_mbox_enable(struct irq_data *data)
+{
+       int cpu;
+       unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+       WARN_ON(mbox >= CIU3_MBOX_PER_CORE);
+
+       for_each_online_cpu(cpu)
+               octeon_irq_ciu3_mbox_set_enable(data, cpu, true);
+}
+
+static void octeon_irq_ciu3_mbox_disable(struct irq_data *data)
+{
+       int cpu;
+       unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+       WARN_ON(mbox >= CIU3_MBOX_PER_CORE);
+
+       for_each_online_cpu(cpu)
+               octeon_irq_ciu3_mbox_set_enable(data, cpu, false);
+}
+
+static void octeon_irq_ciu3_mbox_ack(struct irq_data *data)
+{
+       struct octeon_ciu3_info *ciu3_info;
+       unsigned int intsn;
+       u64 isc_w1c_addr;
+       union cvmx_ciu3_iscx_w1c isc_w1c;
+       unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+       intsn = octeon_irq_ciu3_mbox_intsn_for_core(cvmx_get_local_core_num(), mbox);
+
+       isc_w1c.u64 = 0;
+       isc_w1c.s.raw = 1;
+
+       ciu3_info = __this_cpu_read(octeon_ciu3_info);
+       isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn);
+       cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+       cvmx_read_csr(isc_w1c_addr);
+}
+
+static void octeon_irq_ciu3_mbox_cpu_online(struct irq_data *data)
+{
+       octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), true);
+}
+
+static void octeon_irq_ciu3_mbox_cpu_offline(struct irq_data *data)
+{
+       octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), false);
+}
+
+static int octeon_irq_ciu3_alloc_resources(struct octeon_ciu3_info *ciu3_info)
+{
+       u64 b = ciu3_info->ciu3_addr;
+       int idt_ip2, idt_ip3, idt_ip4;
+       int unused_idt2;
+       int core = cvmx_get_local_core_num();
+       int i;
+
+       __this_cpu_write(octeon_ciu3_info, ciu3_info);
+
+       /*
+        * 4 idt per core starting from 1 because zero is reserved.
+        * Base idt per core is 4 * core + 1
+        */
+       idt_ip2 = core * 4 + 1;
+       idt_ip3 = core * 4 + 2;
+       idt_ip4 = core * 4 + 3;
+       unused_idt2 = core * 4 + 4;
+       __this_cpu_write(octeon_irq_ciu3_idt_ip2, idt_ip2);
+       __this_cpu_write(octeon_irq_ciu3_idt_ip3, idt_ip3);
+
+       /* ip2 interrupts for this CPU */
+       cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip2), 0);
+       cvmx_write_csr(b + CIU3_IDT_PP(idt_ip2, 0), 1ull << core);
+       cvmx_write_csr(b + CIU3_IDT_IO(idt_ip2), 0);
+
+       /* ip3 interrupts for this CPU */
+       cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip3), 1);
+       cvmx_write_csr(b + CIU3_IDT_PP(idt_ip3, 0), 1ull << core);
+       cvmx_write_csr(b + CIU3_IDT_IO(idt_ip3), 0);
+
+       /* ip4 interrupts for this CPU */
+       cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip4), 2);
+       cvmx_write_csr(b + CIU3_IDT_PP(idt_ip4, 0), 0);
+       cvmx_write_csr(b + CIU3_IDT_IO(idt_ip4), 0);
+
+       cvmx_write_csr(b + CIU3_IDT_CTL(unused_idt2), 0);
+       cvmx_write_csr(b + CIU3_IDT_PP(unused_idt2, 0), 0);
+       cvmx_write_csr(b + CIU3_IDT_IO(unused_idt2), 0);
+
+       for (i = 0; i < CIU3_MBOX_PER_CORE; i++) {
+               unsigned int intsn = octeon_irq_ciu3_mbox_intsn_for_core(core, i);
+
+               cvmx_write_csr(b + CIU3_ISC_W1C(intsn), 2);
+               cvmx_write_csr(b + CIU3_ISC_CTL(intsn), 0);
+       }
+
+       return 0;
+}
+
+static void octeon_irq_setup_secondary_ciu3(void)
+{
+       struct octeon_ciu3_info *ciu3_info;
+
+       ciu3_info = octeon_ciu3_info_per_node[cvmx_get_node_num()];
+       octeon_irq_ciu3_alloc_resources(ciu3_info);
+       irq_cpu_online();
+
+       /* Enable the CIU lines */
+       set_c0_status(STATUSF_IP3 | STATUSF_IP2);
+       if (octeon_irq_use_ip4)
+               set_c0_status(STATUSF_IP4);
+       else
+               clear_c0_status(STATUSF_IP4);
+}
+
+static struct irq_chip octeon_irq_chip_ciu3_mbox = {
+       .name = "CIU3-M",
+       .irq_enable = octeon_irq_ciu3_mbox_enable,
+       .irq_disable = octeon_irq_ciu3_mbox_disable,
+       .irq_ack = octeon_irq_ciu3_mbox_ack,
+
+       .irq_cpu_online = octeon_irq_ciu3_mbox_cpu_online,
+       .irq_cpu_offline = octeon_irq_ciu3_mbox_cpu_offline,
+       .flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
+
+static int __init octeon_irq_init_ciu3(struct device_node *ciu_node,
+                                      struct device_node *parent)
+{
+       int i;
+       int node;
+       struct irq_domain *domain;
+       struct octeon_ciu3_info *ciu3_info;
+       const __be32 *zero_addr;
+       u64 base_addr;
+       union cvmx_ciu3_const consts;
+
+       node = 0; /* of_node_to_nid(ciu_node); */
+       ciu3_info = kzalloc_node(sizeof(*ciu3_info), GFP_KERNEL, node);
+
+       if (!ciu3_info)
+               return -ENOMEM;
+
+       zero_addr = of_get_address(ciu_node, 0, NULL, NULL);
+       if (WARN_ON(!zero_addr))
+               return -EINVAL;
+
+       base_addr = of_translate_address(ciu_node, zero_addr);
+       base_addr = (u64)phys_to_virt(base_addr);
+
+       ciu3_info->ciu3_addr = base_addr;
+       ciu3_info->node = node;
+
+       consts.u64 = cvmx_read_csr(base_addr + CIU3_CONST);
+
+       octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu3;
+
+       octeon_irq_ip2 = octeon_irq_ciu3_ip2;
+       octeon_irq_ip3 = octeon_irq_ciu3_mbox;
+       octeon_irq_ip4 = octeon_irq_ip4_mask;
+
+       if (node == cvmx_get_node_num()) {
+               /* Mips internal */
+               octeon_irq_init_core();
+
+               /* Only do per CPU things if it is the CIU of the boot node. */
+               i = irq_alloc_descs_from(OCTEON_IRQ_MBOX0, 8, node);
+               WARN_ON(i < 0);
+
+               for (i = 0; i < 8; i++)
+                       irq_set_chip_and_handler(i + OCTEON_IRQ_MBOX0,
+                                                &octeon_irq_chip_ciu3_mbox, handle_percpu_irq);
+       }
+
+       /*
+        * Initialize all domains to use the default domain. Specific major
+        * blocks will overwrite the default domain as needed.
+        */
+       domain = irq_domain_add_tree(ciu_node, &octeon_dflt_domain_ciu3_ops,
+                                    ciu3_info);
+       for (i = 0; i < MAX_CIU3_DOMAINS; i++)
+               ciu3_info->domain[i] = domain;
+
+       octeon_ciu3_info_per_node[node] = ciu3_info;
+
+       if (node == cvmx_get_node_num()) {
+               /* Only do per CPU things if it is the CIU of the boot node. */
+               octeon_irq_ciu3_alloc_resources(ciu3_info);
+               if (node == 0)
+                       irq_set_default_host(domain);
+
+               octeon_irq_use_ip4 = false;
+               /* Enable the CIU lines */
+               set_c0_status(STATUSF_IP2 | STATUSF_IP3);
+               clear_c0_status(STATUSF_IP4);
+       }
+
+       return 0;
+}
+
 static struct of_device_id ciu_types[] __initdata = {
        {.compatible = "cavium,octeon-3860-ciu", .data = octeon_irq_init_ciu},
        {.compatible = "cavium,octeon-3860-gpio", .data = octeon_irq_init_gpio},
        {.compatible = "cavium,octeon-6880-ciu2", .data = octeon_irq_init_ciu2},
+       {.compatible = "cavium,octeon-7890-ciu3", .data = octeon_irq_init_ciu3},
        {.compatible = "cavium,octeon-7130-cib", .data = octeon_irq_init_cib},
        {}
 };
index d113c8ded6e2f33626ee531fca8d7af3b70c2b47..7aeafedff94edce4bd38017eb31e8432abe233fb 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/usb.h>
 #include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -525,10 +526,17 @@ static void __init octeon_fdt_set_phy(int eth, int phy_addr)
 
 static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
 {
+       const u8 *old_mac;
+       int old_len;
        u8 new_mac[6];
        u64 mac = *pmac;
        int r;
 
+       old_mac = fdt_getprop(initial_boot_params, n, "local-mac-address",
+                             &old_len);
+       if (!old_mac || old_len != 6 || is_valid_ether_addr(old_mac))
+               return;
+
        new_mac[0] = (mac >> 40) & 0xff;
        new_mac[1] = (mac >> 32) & 0xff;
        new_mac[2] = (mac >> 24) & 0xff;
@@ -560,7 +568,7 @@ static void __init octeon_fdt_rm_ethernet(int node)
        fdt_nop_node(initial_boot_params, node);
 }
 
-static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pmac)
+static void __init octeon_fdt_pip_port(int iface, int i, int p, int max)
 {
        char name_buffer[20];
        int eth;
@@ -583,10 +591,9 @@ static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pm
 
        phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
        octeon_fdt_set_phy(eth, phy_addr);
-       octeon_fdt_set_mac_addr(eth, pmac);
 }
 
-static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
+static void __init octeon_fdt_pip_iface(int pip, int idx)
 {
        char name_buffer[20];
        int iface;
@@ -602,7 +609,73 @@ static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
                count = cvmx_helper_ports_on_interface(idx);
 
        for (p = 0; p < 16; p++)
-               octeon_fdt_pip_port(iface, idx, p, count - 1, pmac);
+               octeon_fdt_pip_port(iface, idx, p, count - 1);
+}
+
+void __init octeon_fill_mac_addresses(void)
+{
+       const char *alias_prop;
+       char name_buffer[20];
+       u64 mac_addr_base;
+       int aliases;
+       int pip;
+       int i;
+
+       aliases = fdt_path_offset(initial_boot_params, "/aliases");
+       if (aliases < 0)
+               return;
+
+       mac_addr_base =
+               ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
+               ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
+               ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
+               ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
+               ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
+                (octeon_bootinfo->mac_addr_base[5] & 0xffull);
+
+       for (i = 0; i < 2; i++) {
+               int mgmt;
+
+               snprintf(name_buffer, sizeof(name_buffer), "mix%d", i);
+               alias_prop = fdt_getprop(initial_boot_params, aliases,
+                                        name_buffer, NULL);
+               if (!alias_prop)
+                       continue;
+               mgmt = fdt_path_offset(initial_boot_params, alias_prop);
+               if (mgmt < 0)
+                       continue;
+               octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
+       }
+
+       alias_prop = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
+       if (!alias_prop)
+               return;
+
+       pip = fdt_path_offset(initial_boot_params, alias_prop);
+       if (pip < 0)
+               return;
+
+       for (i = 0; i <= 4; i++) {
+               int iface;
+               int p;
+
+               snprintf(name_buffer, sizeof(name_buffer), "interface@%d", i);
+               iface = fdt_subnode_offset(initial_boot_params, pip,
+                                          name_buffer);
+               if (iface < 0)
+                       continue;
+               for (p = 0; p < 16; p++) {
+                       int eth;
+
+                       snprintf(name_buffer, sizeof(name_buffer),
+                                "ethernet@%x", p);
+                       eth = fdt_subnode_offset(initial_boot_params, iface,
+                                                name_buffer);
+                       if (eth < 0)
+                               continue;
+                       octeon_fdt_set_mac_addr(eth, &mac_addr_base);
+               }
+       }
 }
 
 int __init octeon_prune_device_tree(void)
@@ -612,7 +685,6 @@ int __init octeon_prune_device_tree(void)
        const char *alias_prop;
        char name_buffer[20];
        int aliases;
-       u64 mac_addr_base;
 
        if (fdt_check_header(initial_boot_params))
                panic("Corrupt Device Tree.");
@@ -623,15 +695,6 @@ int __init octeon_prune_device_tree(void)
                return -EINVAL;
        }
 
-
-       mac_addr_base =
-               ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
-               ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
-               ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
-               ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
-               ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
-               (octeon_bootinfo->mac_addr_base[5] & 0xffull);
-
        if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
                max_port = 2;
        else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
@@ -660,7 +723,6 @@ int __init octeon_prune_device_tree(void)
                        } else {
                                int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
                                octeon_fdt_set_phy(mgmt, phy_addr);
-                               octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
                        }
                }
        }
@@ -670,7 +732,7 @@ int __init octeon_prune_device_tree(void)
                int pip = fdt_path_offset(initial_boot_params, pip_path);
                if (pip  >= 0)
                        for (i = 0; i <= 4; i++)
-                               octeon_fdt_pip_iface(pip, i, &mac_addr_base);
+                               octeon_fdt_pip_iface(pip, i);
        }
 
        /* I2C */
index cd7101fb622705c26fa40bfd0f58ca4d23d05dcb..64f852b063a85a6053f69cc5528af8dcb3810cf9 100644 (file)
@@ -43,8 +43,6 @@
 #include <asm/octeon/cvmx-mio-defs.h>
 #include <asm/octeon/cvmx-rst-defs.h>
 
-extern struct plat_smp_ops octeon_smp_ops;
-
 #ifdef CONFIG_PCI
 extern void pci_console_init(const char *arg);
 #endif
@@ -466,15 +464,25 @@ static void octeon_halt(void)
 
 static char __read_mostly octeon_system_type[80];
 
-static int __init init_octeon_system_type(void)
+static void __init init_octeon_system_type(void)
 {
-       snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)",
-               cvmx_board_type_to_string(octeon_bootinfo->board_type),
-               octeon_model_get_string(read_c0_prid()));
+       char const *board_type;
+
+       board_type = cvmx_board_type_to_string(octeon_bootinfo->board_type);
+       if (board_type == NULL) {
+               struct device_node *root;
+               int ret;
+
+               root = of_find_node_by_path("/");
+               ret = of_property_read_string(root, "model", &board_type);
+               of_node_put(root);
+               if (ret)
+                       board_type = "Unsupported Board";
+       }
 
-       return 0;
+       snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)",
+                board_type, octeon_model_get_string(read_c0_prid()));
 }
-early_initcall(init_octeon_system_type);
 
 /**
  * Return a string representing the system type
@@ -492,8 +500,6 @@ const char *get_system_type(void)
 void octeon_user_io_init(void)
 {
        union octeon_cvmemctl cvmmemctl;
-       union cvmx_iob_fau_timeout fau_timeout;
-       union cvmx_pow_nw_tim nm_tim;
 
        /* Get the current settings for CP0_CVMMEMCTL_REG */
        cvmmemctl.u64 = read_c0_cvmmemctl();
@@ -595,17 +601,27 @@ void octeon_user_io_init(void)
                          CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
                          CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
 
-       /* Set a default for the hardware timeouts */
-       fau_timeout.u64 = 0;
-       fau_timeout.s.tout_val = 0xfff;
-       /* Disable tagwait FAU timeout */
-       fau_timeout.s.tout_enb = 0;
-       cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64);
+       if (octeon_has_feature(OCTEON_FEATURE_FAU)) {
+               union cvmx_iob_fau_timeout fau_timeout;
+
+               /* Set a default for the hardware timeouts */
+               fau_timeout.u64 = 0;
+               fau_timeout.s.tout_val = 0xfff;
+               /* Disable tagwait FAU timeout */
+               fau_timeout.s.tout_enb = 0;
+               cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64);
+       }
 
-       nm_tim.u64 = 0;
-       /* 4096 cycles */
-       nm_tim.s.nw_tim = 3;
-       cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64);
+       if ((!OCTEON_IS_MODEL(OCTEON_CN68XX) &&
+            !OCTEON_IS_MODEL(OCTEON_CN7XXX)) ||
+           OCTEON_IS_MODEL(OCTEON_CN70XX)) {
+               union cvmx_pow_nw_tim nm_tim;
+
+               nm_tim.u64 = 0;
+               /* 4096 cycles */
+               nm_tim.s.nw_tim = 3;
+               cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64);
+       }
 
        write_octeon_c0_icacheerr(0);
        write_c0_derraddr1(0);
@@ -637,9 +653,22 @@ void __init prom_init(void)
        sysinfo = cvmx_sysinfo_get();
        memset(sysinfo, 0, sizeof(*sysinfo));
        sysinfo->system_dram_size = octeon_bootinfo->dram_size << 20;
-       sysinfo->phy_mem_desc_ptr =
-               cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr);
-       sysinfo->core_mask = octeon_bootinfo->core_mask;
+       sysinfo->phy_mem_desc_addr = (u64)phys_to_virt(octeon_bootinfo->phy_mem_desc_addr);
+
+       if ((octeon_bootinfo->major_version > 1) ||
+           (octeon_bootinfo->major_version == 1 &&
+            octeon_bootinfo->minor_version >= 4))
+               cvmx_coremask_copy(&sysinfo->core_mask,
+                                  &octeon_bootinfo->ext_core_mask);
+       else
+               cvmx_coremask_set64(&sysinfo->core_mask,
+                                   octeon_bootinfo->core_mask);
+
+       /* Some broken u-boot pass garbage in upper bits, clear them out */
+       if (!OCTEON_IS_MODEL(OCTEON_CN78XX))
+               for (i = 512; i < 1024; i++)
+                       cvmx_coremask_clear_core(&sysinfo->core_mask, i);
+
        sysinfo->exception_base_addr = octeon_bootinfo->exception_base_addr;
        sysinfo->cpu_clock_hz = octeon_bootinfo->eclock_hz;
        sysinfo->dram_data_rate_hz = octeon_bootinfo->dclock_hz * 2;
@@ -867,7 +896,7 @@ void __init prom_init(void)
 #endif
 
        octeon_user_io_init();
-       register_smp_ops(&octeon_smp_ops);
+       octeon_setup_smp();
 }
 
 /* Exclude a single page from the regions obtained in plat_mem_setup. */
@@ -1079,6 +1108,7 @@ void __init prom_free_prom_memory(void)
        }
 }
 
+void __init octeon_fill_mac_addresses(void);
 int octeon_prune_device_tree(void);
 
 extern const char __appended_dtb;
@@ -1088,11 +1118,13 @@ void __init device_tree_init(void)
 {
        const void *fdt;
        bool do_prune;
+       bool fill_mac;
 
 #ifdef CONFIG_MIPS_ELF_APPENDED_DTB
        if (!fdt_check_header(&__appended_dtb)) {
                fdt = &__appended_dtb;
                do_prune = false;
+               fill_mac = true;
                pr_info("Using appended Device Tree.\n");
        } else
 #endif
@@ -1101,13 +1133,16 @@ void __init device_tree_init(void)
                if (fdt_check_header(fdt))
                        panic("Corrupt Device Tree passed to kernel.");
                do_prune = false;
+               fill_mac = false;
                pr_info("Using passed Device Tree.\n");
        } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
                fdt = &__dtb_octeon_68xx_begin;
                do_prune = true;
+               fill_mac = true;
        } else {
                fdt = &__dtb_octeon_3xxx_begin;
                do_prune = true;
+               fill_mac = true;
        }
 
        initial_boot_params = (void *)fdt;
@@ -1116,7 +1151,10 @@ void __init device_tree_init(void)
                octeon_prune_device_tree();
                pr_info("Using internal Device Tree.\n");
        }
+       if (fill_mac)
+               octeon_fill_mac_addresses();
        unflatten_and_copy_device_tree();
+       init_octeon_system_type();
 }
 
 static int __initdata disable_octeon_edac_p;
index 42412ba0f3bfd78f1f7f6f6046fd581d4641bc56..dff88aa7e3778e9ec55d7edee2106fcaf84db7d2 100644 (file)
@@ -30,25 +30,55 @@ uint64_t octeon_bootloader_entry_addr;
 EXPORT_SYMBOL(octeon_bootloader_entry_addr);
 #endif
 
+static void octeon_icache_flush(void)
+{
+       asm volatile ("synci 0($0)\n");
+}
+
+static void (*octeon_message_functions[8])(void) = {
+       scheduler_ipi,
+       generic_smp_call_function_interrupt,
+       octeon_icache_flush,
+};
+
 static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
 {
-       const int coreid = cvmx_get_core_num();
-       uint64_t action;
+       u64 mbox_clrx = CVMX_CIU_MBOX_CLRX(cvmx_get_core_num());
+       u64 action;
+       int i;
+
+       /*
+        * Make sure the function array initialization remains
+        * correct.
+        */
+       BUILD_BUG_ON(SMP_RESCHEDULE_YOURSELF != (1 << 0));
+       BUILD_BUG_ON(SMP_CALL_FUNCTION       != (1 << 1));
+       BUILD_BUG_ON(SMP_ICACHE_FLUSH        != (1 << 2));
+
+       /*
+        * Load the mailbox register to figure out what we're supposed
+        * to do.
+        */
+       action = cvmx_read_csr(mbox_clrx);
 
-       /* Load the mailbox register to figure out what we're supposed to do */
-       action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid)) & 0xffff;
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+               action &= 0xff;
+       else
+               action &= 0xffff;
 
        /* Clear the mailbox to clear the interrupt */
-       cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
+       cvmx_write_csr(mbox_clrx, action);
 
-       if (action & SMP_CALL_FUNCTION)
-               generic_smp_call_function_interrupt();
-       if (action & SMP_RESCHEDULE_YOURSELF)
-               scheduler_ipi();
+       for (i = 0; i < ARRAY_SIZE(octeon_message_functions) && action;) {
+               if (action & 1) {
+                       void (*fn)(void) = octeon_message_functions[i];
 
-       /* Check if we've been told to flush the icache */
-       if (action & SMP_ICACHE_FLUSH)
-               asm volatile ("synci 0($0)\n");
+                       if (fn)
+                               fn();
+               }
+               action >>= 1;
+               i++;
+       }
        return IRQ_HANDLED;
 }
 
@@ -97,13 +127,15 @@ static void octeon_smp_hotplug_setup(void)
 #endif
 }
 
-static void octeon_smp_setup(void)
+static void __init octeon_smp_setup(void)
 {
        const int coreid = cvmx_get_core_num();
        int cpus;
        int id;
-       int core_mask = octeon_get_boot_coremask();
+       struct cvmx_sysinfo *sysinfo = cvmx_sysinfo_get();
+
 #ifdef CONFIG_HOTPLUG_CPU
+       int core_mask = octeon_get_boot_coremask();
        unsigned int num_cores = cvmx_octeon_num_cores();
 #endif
 
@@ -119,7 +151,7 @@ static void octeon_smp_setup(void)
        /* The present CPUs get the lowest CPU numbers. */
        cpus = 1;
        for (id = 0; id < NR_CPUS; id++) {
-               if ((id != coreid) && (core_mask & (1 << id))) {
+               if ((id != coreid) && cvmx_coremask_is_core_set(&sysinfo->core_mask, id)) {
                        set_cpu_possible(cpus, true);
                        set_cpu_present(cpus, true);
                        __cpu_number_map[id] = cpus;
@@ -196,7 +228,7 @@ static void octeon_init_secondary(void)
  * Callout to firmware before smp_init
  *
  */
-void octeon_prepare_cpus(unsigned int max_cpus)
+static void __init octeon_prepare_cpus(unsigned int max_cpus)
 {
        /*
         * Only the low order mailbox bits are used for IPIs, leave
@@ -242,7 +274,7 @@ static int octeon_cpu_disable(void)
        cpumask_clear_cpu(cpu, &cpu_callin_map);
        octeon_fixup_irqs();
 
-       flush_cache_all();
+       __flush_cache_all();
        local_flush_tlb_all();
 
        return 0;
@@ -388,3 +420,92 @@ struct plat_smp_ops octeon_smp_ops = {
        .cpu_die                = octeon_cpu_die,
 #endif
 };
+
+static irqreturn_t octeon_78xx_reched_interrupt(int irq, void *dev_id)
+{
+       scheduler_ipi();
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t octeon_78xx_call_function_interrupt(int irq, void *dev_id)
+{
+       generic_smp_call_function_interrupt();
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t octeon_78xx_icache_flush_interrupt(int irq, void *dev_id)
+{
+       octeon_icache_flush();
+       return IRQ_HANDLED;
+}
+
+/*
+ * Callout to firmware before smp_init
+ */
+static void octeon_78xx_prepare_cpus(unsigned int max_cpus)
+{
+       if (request_irq(OCTEON_IRQ_MBOX0 + 0,
+                       octeon_78xx_reched_interrupt,
+                       IRQF_PERCPU | IRQF_NO_THREAD, "Scheduler",
+                       octeon_78xx_reched_interrupt)) {
+               panic("Cannot request_irq for SchedulerIPI");
+       }
+       if (request_irq(OCTEON_IRQ_MBOX0 + 1,
+                       octeon_78xx_call_function_interrupt,
+                       IRQF_PERCPU | IRQF_NO_THREAD, "SMP-Call",
+                       octeon_78xx_call_function_interrupt)) {
+               panic("Cannot request_irq for SMP-Call");
+       }
+       if (request_irq(OCTEON_IRQ_MBOX0 + 2,
+                       octeon_78xx_icache_flush_interrupt,
+                       IRQF_PERCPU | IRQF_NO_THREAD, "ICache-Flush",
+                       octeon_78xx_icache_flush_interrupt)) {
+               panic("Cannot request_irq for ICache-Flush");
+       }
+}
+
+static void octeon_78xx_send_ipi_single(int cpu, unsigned int action)
+{
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               if (action & 1)
+                       octeon_ciu3_mbox_send(cpu, i);
+               action >>= 1;
+       }
+}
+
+static void octeon_78xx_send_ipi_mask(const struct cpumask *mask,
+                                     unsigned int action)
+{
+       unsigned int cpu;
+
+       for_each_cpu(cpu, mask)
+               octeon_78xx_send_ipi_single(cpu, action);
+}
+
+static struct plat_smp_ops octeon_78xx_smp_ops = {
+       .send_ipi_single        = octeon_78xx_send_ipi_single,
+       .send_ipi_mask          = octeon_78xx_send_ipi_mask,
+       .init_secondary         = octeon_init_secondary,
+       .smp_finish             = octeon_smp_finish,
+       .boot_secondary         = octeon_boot_secondary,
+       .smp_setup              = octeon_smp_setup,
+       .prepare_cpus           = octeon_78xx_prepare_cpus,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_disable            = octeon_cpu_disable,
+       .cpu_die                = octeon_cpu_die,
+#endif
+};
+
+void __init octeon_setup_smp(void)
+{
+       struct plat_smp_ops *ops;
+
+       if (octeon_has_feature(OCTEON_FEATURE_CIU3))
+               ops = &octeon_78xx_smp_ops;
+       else
+               ops = &octeon_smp_ops;
+
+       register_smp_ops(ops);
+}
index 0db4eb319e0a3f9afdc9264d4ca4b21a7e3dd53c..fad8e964f14ca4cf0d7de518471c35faeceb7d6e 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_IP_MROUTE=y
 CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
 CONFIG_SYN_COOKIES=y
 CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_IPV6_MROUTE=y
index 3fec26410f344f0bb3af8a36252a515235104507..5599a9f1e3c676ff0dffdfd033b1919031c64ead 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_MTD=y
+CONFIG_MTD_BCM63XX_PARTS=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
index e070dac071c89955658e876de197b98fbb479d8a..d20b09d77b534b1f883af2853568ad80d5e1c262 100644 (file)
@@ -62,7 +62,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 # CONFIG_INET_LRO is not set
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
index 24dcb90b0f64b993dae12cd30a3e1aa5a6933f58..acf7785c4cdb750df3c842a41dba5fdf41ce89b5 100644 (file)
@@ -36,6 +36,7 @@ CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_PRINTK_TIME=y
 CONFIG_BRCMSTB_GISB_ARB=y
 CONFIG_MTD=y
+CONFIG_MTD_BCM63XX_PARTS=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
index e57058d4ec2294f99e73bd84502293d7b4601def..dcac308cec39d470d70ed270020e9ab86db23cd3 100644 (file)
@@ -119,14 +119,16 @@ CONFIG_SPI=y
 CONFIG_SPI_OCTEON=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
-# CONFIG_USB_SUPPORT is not set
-CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_HCD_PLATFORM=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PLATFORM=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_STAGING=y
 CONFIG_OCTEON_ETHERNET=y
+CONFIG_OCTEON_USB=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
@@ -152,6 +154,9 @@ CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MD5_OCTEON=y
+CONFIG_CRYPTO_SHA1_OCTEON=m
+CONFIG_CRYPTO_SHA256_OCTEON=m
+CONFIG_CRYPTO_SHA512_OCTEON=m
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index ebc011c51e5a4220bdf74f27044217390ea13477..2b6cb41d571591adf847e4345db70e3897a009d1 100644 (file)
@@ -30,7 +30,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
index 6ba9ce9fcdd54ca8671f65d35cb2cff31dd7af39..5d83ff7555477f9284fcd952dfc5b8d9c33c1bd2 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
index 77e9f505f5e4380aab069cb2119afe56b642df3f..2b74aee320a12fae4a79cb439650e5ed2c2f575e 100644 (file)
@@ -43,7 +43,6 @@ CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
index a5e85e1ee5de43b246250d5f63e50b386b135e56..3019fce63cd36cc7c4482c9c0fd8fb0e8c08f7e1 100644 (file)
@@ -34,7 +34,6 @@ CONFIG_IP_PIMSM_V2=y
 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_INET6_AH=m
index d1f198b072a0f17520491bacecc901fe88d11a06..5da76e0e120f59fc788d98c11f0a949f9fbc30db 100644 (file)
@@ -71,7 +71,6 @@ CONFIG_TCP_CONG_ADVANCED=y
 CONFIG_TCP_CONG_BIC=y
 CONFIG_DEFAULT_BIC=y
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_TUNNEL=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
similarity index 84%
rename from arch/mips/configs/ls1b_defconfig
rename to arch/mips/configs/loongson1b_defconfig
index 1b2cc1fb26a165189630a79f06c6ce39459edb34..c442f27685f4fd9338ea57cdc1d1a463a11eaf33 100644 (file)
@@ -1,19 +1,17 @@
 CONFIG_MACH_LOONGSON32=y
 CONFIG_PREEMPT=y
 # CONFIG_SECCOMP is not set
-CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
 CONFIG_SYSVIPC=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_NAMESPACES=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_RD_BZIP2=y
-CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_EXPERT=y
 CONFIG_PERF_EVENTS=y
 # CONFIG_COMPAT_BRK is not set
@@ -41,6 +39,12 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_LOONGSON1=y
+CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_SCSI=m
 # CONFIG_SCSI_PROC_FS is not set
@@ -48,7 +52,6 @@ CONFIG_BLK_DEV_SD=m
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
@@ -56,7 +59,6 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 CONFIG_STMMAC_ETH=y
-CONFIG_STMMAC_DA=y
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_WLAN is not set
 CONFIG_INPUT_EVDEV=y
@@ -69,18 +71,25 @@ CONFIG_LEGACY_PTY_COUNT=8
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
 # CONFIG_VGA_CONSOLE is not set
-CONFIG_USB_HID=m
 CONFIG_HID_GENERIC=m
+CONFIG_USB_HID=m
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_HCD_PLATFORM=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=m
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_PL2303=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_LOONGSON1=y
 # CONFIG_IOMMU_SUPPORT is not set
@@ -96,15 +105,21 @@ CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_ISO8859_1=m
+CONFIG_DYNAMIC_DEBUG=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_FTRACE is not set
 # CONFIG_EARLY_PRINTK is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+# CONFIG_CRYPTO_HW is not set
index 9b6926d6bb3294cfff7f87b832f683249089c065..f3f60056bc274915fdeaf47f03a8a1b1eb8c0166 100644 (file)
@@ -51,7 +51,6 @@ CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
index b3d1d37f85eace0778eaa57c3f8aa616aebf531c..b496c25fced6c5935f64db81fe04d6e54a0934ba 100644 (file)
@@ -95,7 +95,6 @@ CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
index 3d8016d6cf3eb143ff8b262e8a8de099fb41863a..8e99ad807a57c20c8ee7b288941deb6383de6812 100644 (file)
@@ -75,7 +75,6 @@ CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
index 82db4e3e4cf1947869989ae090a33de8413ea85c..c2b4e3f33a7382c84316c45f9fa31e72d462af06 100644 (file)
@@ -37,7 +37,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
index a0b8943c8f11b9b89bc3c92f3b290c99b309710b..1c3bf9fe926ff50d4a07a58f584518561ef31158 100644 (file)
@@ -60,6 +60,7 @@ EXPORT_SYMBOL(dec_kn_slot_size);
 int dec_tc_bus;
 
 DEFINE_SPINLOCK(ioasic_ssr_lock);
+EXPORT_SYMBOL(ioasic_ssr_lock);
 
 volatile u32 *ioasic_base;
 
index c7fe4d01e79c61bbaee58aa25b9b50bf5b9a380e..9740066cc631f097b3e6682509ceb39f292b4316 100644 (file)
@@ -1,5 +1,6 @@
 # MIPS headers
 generic-(CONFIG_GENERIC_CSUM) += checksum.h
+generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += dma-contiguous.h
index 867f924b05c79522a2d397d0002bc8a1397319e2..6741673c92cadc39abaea44dc57766fcde50a9e4 100644 (file)
        .macro  ld_b    wd, off, base
        .set    push
        .set    mips32r2
+       .set    fp=64
        .set    msa
        ld.b    $w\wd, \off(\base)
        .set    pop
        .macro  ld_h    wd, off, base
        .set    push
        .set    mips32r2
+       .set    fp=64
        .set    msa
        ld.h    $w\wd, \off(\base)
        .set    pop
        .macro  ld_w    wd, off, base
        .set    push
        .set    mips32r2
+       .set    fp=64
        .set    msa
        ld.w    $w\wd, \off(\base)
        .set    pop
        .macro  st_b    wd, off, base
        .set    push
        .set    mips32r2
+       .set    fp=64
        .set    msa
        st.b    $w\wd, \off(\base)
        .set    pop
        .macro  st_h    wd, off, base
        .set    push
        .set    mips32r2
+       .set    fp=64
        .set    msa
        st.h    $w\wd, \off(\base)
        .set    pop
        .macro  st_w    wd, off, base
        .set    push
        .set    mips32r2
+       .set    fp=64
        .set    msa
        st.w    $w\wd, \off(\base)
        .set    pop
        .set    pop
        .endm
 
-       .macro  copy_u_w        ws, n
+       .macro  copy_s_w        ws, n
        .set    push
        .set    mips32r2
        .set    fp=64
        .set    msa
-       copy_u.w $1, $w\ws[\n]
+       copy_s.w $1, $w\ws[\n]
        .set    pop
        .endm
 
-       .macro  copy_u_d        ws, n
+       .macro  copy_s_d        ws, n
        .set    push
        .set    mips64r2
        .set    fp=64
        .set    msa
-       copy_u.d $1, $w\ws[\n]
+       copy_s.d $1, $w\ws[\n]
        .set    pop
        .endm
 
 #define STH_MSA_INSN           0x5800081f
 #define STW_MSA_INSN           0x5800082f
 #define STD_MSA_INSN           0x5800083f
-#define COPY_UW_MSA_INSN       0x58f00056
-#define COPY_UD_MSA_INSN       0x58f80056
+#define COPY_SW_MSA_INSN       0x58b00056
+#define COPY_SD_MSA_INSN       0x58b80056
 #define INSERT_W_MSA_INSN      0x59300816
 #define INSERT_D_MSA_INSN      0x59380816
 #else
 #define STH_MSA_INSN           0x78000825
 #define STW_MSA_INSN           0x78000826
 #define STD_MSA_INSN           0x78000827
-#define COPY_UW_MSA_INSN       0x78f00059
-#define COPY_UD_MSA_INSN       0x78f80059
+#define COPY_SW_MSA_INSN       0x78b00059
+#define COPY_SD_MSA_INSN       0x78b80059
 #define INSERT_W_MSA_INSN      0x79300819
 #define INSERT_D_MSA_INSN      0x79380819
 #endif
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   LDB_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   LDH_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   LDW_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   LDD_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   STB_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   STH_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   STW_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
        .set    push
        .set    noat
        SET_HARDFLOAT
-       addu    $1, \base, \off
+       PTR_ADDU $1, \base, \off
        .word   STD_MSA_INSN | (\wd << 6)
        .set    pop
        .endm
 
-       .macro  copy_u_w        ws, n
+       .macro  copy_s_w        ws, n
        .set    push
        .set    noat
        SET_HARDFLOAT
        .insn
-       .word   COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
+       .word   COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11)
        .set    pop
        .endm
 
-       .macro  copy_u_d        ws, n
+       .macro  copy_s_d        ws, n
        .set    push
        .set    noat
        SET_HARDFLOAT
        .insn
-       .word   COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
+       .word   COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11)
        .set    pop
        .endm
 
        .endm
 #endif
 
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+#define FPR_BASE_OFFS  THREAD_FPR0
+#define FPR_BASE       $1
+#else
+#define FPR_BASE_OFFS  0
+#define FPR_BASE       \thread
+#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
        .set    push
        .set    noat
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+       PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS
+#endif
+       st_d     0, THREAD_FPR0  - FPR_BASE_OFFS, FPR_BASE
+       st_d     1, THREAD_FPR1  - FPR_BASE_OFFS, FPR_BASE
+       st_d     2, THREAD_FPR2  - FPR_BASE_OFFS, FPR_BASE
+       st_d     3, THREAD_FPR3  - FPR_BASE_OFFS, FPR_BASE
+       st_d     4, THREAD_FPR4  - FPR_BASE_OFFS, FPR_BASE
+       st_d     5, THREAD_FPR5  - FPR_BASE_OFFS, FPR_BASE
+       st_d     6, THREAD_FPR6  - FPR_BASE_OFFS, FPR_BASE
+       st_d     7, THREAD_FPR7  - FPR_BASE_OFFS, FPR_BASE
+       st_d     8, THREAD_FPR8  - FPR_BASE_OFFS, FPR_BASE
+       st_d     9, THREAD_FPR9  - FPR_BASE_OFFS, FPR_BASE
+       st_d    10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE
+       st_d    11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE
+       st_d    12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE
+       st_d    13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE
+       st_d    14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE
+       st_d    15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE
+       st_d    16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE
+       st_d    17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE
+       st_d    18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE
+       st_d    19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE
+       st_d    20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE
+       st_d    21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE
+       st_d    22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE
+       st_d    23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE
+       st_d    24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE
+       st_d    25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE
+       st_d    26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE
+       st_d    27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE
+       st_d    28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE
+       st_d    29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE
+       st_d    30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE
+       st_d    31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE
        SET_HARDFLOAT
        _cfcmsa $1, MSA_CSR
        sw      $1, THREAD_MSA_CSR(\thread)
        SET_HARDFLOAT
        lw      $1, THREAD_MSA_CSR(\thread)
        _ctcmsa MSA_CSR, $1
-       .set    pop
-       ld_d    0, THREAD_FPR0, \thread
-       ld_d    1, THREAD_FPR1, \thread
-       ld_d    2, THREAD_FPR2, \thread
-       ld_d    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
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+       PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS
+#endif
+       ld_d     0, THREAD_FPR0  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     1, THREAD_FPR1  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     2, THREAD_FPR2  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     3, THREAD_FPR3  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     4, THREAD_FPR4  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     5, THREAD_FPR5  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     6, THREAD_FPR6  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     7, THREAD_FPR7  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     8, THREAD_FPR8  - FPR_BASE_OFFS, FPR_BASE
+       ld_d     9, THREAD_FPR9  - FPR_BASE_OFFS, FPR_BASE
+       ld_d    10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE
+       ld_d    31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE
+       .set pop
+       .endm
+
+#undef FPR_BASE_OFFS
+#undef FPR_BASE
 
        .macro  msa_init_upper wd
 #ifdef CONFIG_64BIT
index ce9666cf14995ce1b713cccce029244ca5ba24b5..fa57cef12a4664acb29cf8780ed864dd52d68b0d 100644 (file)
 #include <asm/byteorder.h>             /* sigh ... */
 #include <asm/compiler.h>
 #include <asm/cpu-features.h>
+#include <asm/llsc.h>
 #include <asm/sgidefs.h>
 #include <asm/war.h>
 
-#if _MIPS_SZLONG == 32
-#define SZLONG_LOG 5
-#define SZLONG_MASK 31UL
-#define __LL           "ll     "
-#define __SC           "sc     "
-#define __INS          "ins    "
-#define __EXT          "ext    "
-#elif _MIPS_SZLONG == 64
-#define SZLONG_LOG 6
-#define SZLONG_MASK 63UL
-#define __LL           "lld    "
-#define __SC           "scd    "
-#define __INS          "dins    "
-#define __EXT          "dext    "
-#endif
-
 /*
  * These are the "slower" versions of the functions and are in bitops.c.
  * These functions call raw_local_irq_{save,restore}().
diff --git a/arch/mips/include/asm/bitrev.h b/arch/mips/include/asm/bitrev.h
new file mode 100644 (file)
index 0000000..bc739a4
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __MIPS_ASM_BITREV_H__
+#define __MIPS_ASM_BITREV_H__
+
+#include <linux/swab.h>
+
+static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x)
+{
+       u32 ret;
+
+       asm("bitswap    %0, %1" : "=r"(ret) : "r"(__swab32(x)));
+       return ret;
+}
+
+static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x)
+{
+       u16 ret;
+
+       asm("bitswap    %0, %1" : "=r"(ret) : "r"(__swab16(x)));
+       return ret;
+}
+
+static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x)
+{
+       u8 ret;
+
+       asm("bitswap    %0, %1" : "=r"(ret) : "r"(x));
+       return ret;
+}
+
+#endif /* __MIPS_ASM_BITREV_H__ */
index 6d25ad33ec78fa5825c3eb58158cc901b82cf399..a92aee7b977acb56539f74f7f9db2d9d0c1291a5 100644 (file)
@@ -88,6 +88,7 @@ extern unsigned long bmips_tp1_irqs;
 
 extern void bmips_ebase_setup(void);
 extern asmlinkage void plat_wired_tlb_setup(void);
+extern void bmips_cpu_setup(void);
 
 static inline unsigned long bmips_read_zscm_reg(unsigned int offset)
 {
index b603804caac5eba01a5c450200cead501b64125c..9f67033961a638acb4d845ba8e0f5fd204409929 100644 (file)
@@ -144,4 +144,22 @@ static inline void plat_swiotlb_setup(void) {}
 
 #endif /* CONFIG_SWIOTLB */
 
+#ifdef CONFIG_USE_OF
+/**
+ * plat_get_fdt() - Return a pointer to the platform's device tree blob
+ *
+ * This function provides a platform independent API to get a pointer to the
+ * flattened device tree blob. The interface between bootloader and kernel
+ * is not consistent across platforms so it is necessary to provide this
+ * API such that common startup code can locate the FDT.
+ *
+ * This is used by the KASLR code to get command line arguments and random
+ * seed from the device tree. Any platform wishing to use KASLR should
+ * provide this API and select SYS_SUPPORTS_RELOCATABLE.
+ *
+ * Return: Pointer to the flattened device tree blob.
+ */
+extern void *plat_get_fdt(void);
+#endif /* CONFIG_USE_OF */
+
 #endif /* _ASM_BOOTINFO_H */
index 723229f4cf278fdb5b50ecfef82d4da55b49cfbb..34ed22ec6c33e7917386b31007f6f14e597a1e10 100644 (file)
@@ -51,7 +51,6 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma,
        unsigned long start, unsigned long end);
 extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
 extern void __flush_dcache_page(struct page *page);
-extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page);
 
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 static inline void flush_dcache_page(struct page *page)
@@ -77,11 +76,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
 static inline void flush_icache_page(struct vm_area_struct *vma,
        struct page *page)
 {
-       if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) &&
-           Page_dcache_dirty(page)) {
-               __flush_icache_page(vma, page);
-               ClearPageDcacheDirty(page);
-       }
 }
 
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
@@ -132,6 +126,7 @@ static inline void kunmap_noncoherent(void)
 static inline void flush_kernel_dcache_page(struct page *page)
 {
        BUG_ON(cpu_has_dc_aliases && PageHighMem(page));
+       flush_dcache_page(page);
 }
 
 /*
index c3212ff2672343fcb52315403c73d16759be77b1..8031fbc6b69a2867a043ff4e1655497548631e72 100644 (file)
@@ -21,6 +21,7 @@
 #define Cache_I                                0x00
 #define Cache_D                                0x01
 #define Cache_T                                0x02
+#define Cache_V                                0x02 /* Loongson-3 */
 #define Cache_S                                0x03
 
 #define Index_Writeback_Inv            0x00
  */
 #define Hit_Invalidate_I_Loongson2     (Cache_I | 0x00)
 
+/*
+ * Loongson3-specific cacheops
+ */
+#define Index_Writeback_Inv_V          (Cache_V | Index_Writeback_Inv)
+
 #endif /* __ASM_CACHEOPS_H */
diff --git a/arch/mips/include/asm/clkdev.h b/arch/mips/include/asm/clkdev.h
deleted file mode 100644 (file)
index 1b3ad7b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  based on arch/arm/include/asm/clkdev.h
- *
- *  Copyright (C) 2008 Russell King.
- *
- * 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.
- *
- * Helper for the clk API to assist looking up a struct clk.
- */
-#ifndef __ASM_CLKDEV_H
-#define __ASM_CLKDEV_H
-
-#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)
-{
-       return kzalloc(size, GFP_KERNEL);
-}
-
-#endif
index eeec8c8e2da2ed59e3d89d099721209203e9c243..e6f19fc61bf254d6fa05fdbec1164f76dca11c39 100644 (file)
@@ -35,6 +35,9 @@
 #ifndef cpu_has_htw
 #define cpu_has_htw            (cpu_data[0].options & MIPS_CPU_HTW)
 #endif
+#ifndef cpu_has_ldpte
+#define cpu_has_ldpte          (cpu_data[0].options & MIPS_CPU_LDPTE)
+#endif
 #ifndef cpu_has_rixiex
 #define cpu_has_rixiex         (cpu_data[0].options & MIPS_CPU_RIXIEX)
 #endif
 #ifndef kernel_uses_llsc
 #define kernel_uses_llsc       cpu_has_llsc
 #endif
+#ifndef cpu_has_guestctl0ext
+#define cpu_has_guestctl0ext   (cpu_data[0].options & MIPS_CPU_GUESTCTL0EXT)
+#endif
+#ifndef cpu_has_guestctl1
+#define cpu_has_guestctl1      (cpu_data[0].options & MIPS_CPU_GUESTCTL1)
+#endif
+#ifndef cpu_has_guestctl2
+#define cpu_has_guestctl2      (cpu_data[0].options & MIPS_CPU_GUESTCTL2)
+#endif
+#ifndef cpu_has_guestid
+#define cpu_has_guestid                (cpu_data[0].options & MIPS_CPU_GUESTID)
+#endif
+#ifndef cpu_has_drg
+#define cpu_has_drg            (cpu_data[0].options & MIPS_CPU_DRG)
+#endif
 #ifndef cpu_has_mips16
 #define cpu_has_mips16         (cpu_data[0].ases & MIPS_ASE_MIPS16)
 #endif
 # endif
 #endif
 
+#ifndef cpu_has_lpa
+#define cpu_has_lpa            (cpu_data[0].options & MIPS_CPU_LPA)
+#endif
+#ifndef cpu_has_mvh
+#define cpu_has_mvh            (cpu_data[0].options & MIPS_CPU_MVH)
+#endif
 #ifndef cpu_has_xpa
-#define cpu_has_xpa            (cpu_data[0].options & MIPS_CPU_XPA)
+#define cpu_has_xpa            (cpu_has_lpa && cpu_has_mvh)
 #endif
 #ifndef cpu_has_vtag_icache
 #define cpu_has_vtag_icache    (cpu_data[0].icache.flags & MIPS_CACHE_VTAG)
 #define cpu_has_dsp2           (cpu_data[0].ases & MIPS_ASE_DSP2P)
 #endif
 
+#ifndef cpu_has_dsp3
+#define cpu_has_dsp3           (cpu_data[0].ases & MIPS_ASE_DSP3)
+#endif
+
 #ifndef cpu_has_mipsmt
 #define cpu_has_mipsmt         (cpu_data[0].ases & MIPS_ASE_MIPSMT)
 #endif
 
+#ifndef cpu_has_vp
+#define cpu_has_vp             (cpu_data[0].options & MIPS_CPU_VP)
+#endif
+
 #ifndef cpu_has_userlocal
 #define cpu_has_userlocal      (cpu_data[0].options & MIPS_CPU_ULRI)
 #endif
 #define cpu_has_nan_2008       (cpu_data[0].options & MIPS_CPU_NAN_2008)
 #endif
 
+#ifndef cpu_has_ebase_wg
+# define cpu_has_ebase_wg      (cpu_data[0].options & MIPS_CPU_EBASE_WG)
+#endif
+
+#ifndef cpu_has_badinstr
+# define cpu_has_badinstr      (cpu_data[0].options & MIPS_CPU_BADINSTR)
+#endif
+
+#ifndef cpu_has_badinstrp
+# define cpu_has_badinstrp     (cpu_data[0].options & MIPS_CPU_BADINSTRP)
+#endif
+
+#ifndef cpu_has_contextconfig
+# define cpu_has_contextconfig (cpu_data[0].options & MIPS_CPU_CTXTC)
+#endif
+
+#ifndef cpu_has_perf
+# define cpu_has_perf          (cpu_data[0].options & MIPS_CPU_PERF)
+#endif
+
+/*
+ * Guest capabilities
+ */
+#ifndef cpu_guest_has_conf1
+#define cpu_guest_has_conf1    (cpu_data[0].guest.conf & (1 << 1))
+#endif
+#ifndef cpu_guest_has_conf2
+#define cpu_guest_has_conf2    (cpu_data[0].guest.conf & (1 << 2))
+#endif
+#ifndef cpu_guest_has_conf3
+#define cpu_guest_has_conf3    (cpu_data[0].guest.conf & (1 << 3))
+#endif
+#ifndef cpu_guest_has_conf4
+#define cpu_guest_has_conf4    (cpu_data[0].guest.conf & (1 << 4))
+#endif
+#ifndef cpu_guest_has_conf5
+#define cpu_guest_has_conf5    (cpu_data[0].guest.conf & (1 << 5))
+#endif
+#ifndef cpu_guest_has_conf6
+#define cpu_guest_has_conf6    (cpu_data[0].guest.conf & (1 << 6))
+#endif
+#ifndef cpu_guest_has_conf7
+#define cpu_guest_has_conf7    (cpu_data[0].guest.conf & (1 << 7))
+#endif
+#ifndef cpu_guest_has_fpu
+#define cpu_guest_has_fpu      (cpu_data[0].guest.options & MIPS_CPU_FPU)
+#endif
+#ifndef cpu_guest_has_watch
+#define cpu_guest_has_watch    (cpu_data[0].guest.options & MIPS_CPU_WATCH)
+#endif
+#ifndef cpu_guest_has_contextconfig
+#define cpu_guest_has_contextconfig (cpu_data[0].guest.options & MIPS_CPU_CTXTC)
+#endif
+#ifndef cpu_guest_has_segments
+#define cpu_guest_has_segments (cpu_data[0].guest.options & MIPS_CPU_SEGMENTS)
+#endif
+#ifndef cpu_guest_has_badinstr
+#define cpu_guest_has_badinstr (cpu_data[0].guest.options & MIPS_CPU_BADINSTR)
+#endif
+#ifndef cpu_guest_has_badinstrp
+#define cpu_guest_has_badinstrp        (cpu_data[0].guest.options & MIPS_CPU_BADINSTRP)
+#endif
+#ifndef cpu_guest_has_htw
+#define cpu_guest_has_htw      (cpu_data[0].guest.options & MIPS_CPU_HTW)
+#endif
+#ifndef cpu_guest_has_msa
+#define cpu_guest_has_msa      (cpu_data[0].guest.ases & MIPS_ASE_MSA)
+#endif
+#ifndef cpu_guest_has_kscr
+#define cpu_guest_has_kscr(n)  (cpu_data[0].guest.kscratch_mask & (1u << (n)))
+#endif
+#ifndef cpu_guest_has_rw_llb
+#define cpu_guest_has_rw_llb   (cpu_has_mips_r6 || (cpu_data[0].guest.options & MIPS_CPU_RW_LLB))
+#endif
+#ifndef cpu_guest_has_perf
+#define cpu_guest_has_perf     (cpu_data[0].guest.options & MIPS_CPU_PERF)
+#endif
+#ifndef cpu_guest_has_maar
+#define cpu_guest_has_maar     (cpu_data[0].guest.options & MIPS_CPU_MAAR)
+#endif
+
+/*
+ * Guest dynamic capabilities
+ */
+#ifndef cpu_guest_has_dyn_fpu
+#define cpu_guest_has_dyn_fpu  (cpu_data[0].guest.options_dyn & MIPS_CPU_FPU)
+#endif
+#ifndef cpu_guest_has_dyn_watch
+#define cpu_guest_has_dyn_watch        (cpu_data[0].guest.options_dyn & MIPS_CPU_WATCH)
+#endif
+#ifndef cpu_guest_has_dyn_contextconfig
+#define cpu_guest_has_dyn_contextconfig (cpu_data[0].guest.options_dyn & MIPS_CPU_CTXTC)
+#endif
+#ifndef cpu_guest_has_dyn_perf
+#define cpu_guest_has_dyn_perf (cpu_data[0].guest.options_dyn & MIPS_CPU_PERF)
+#endif
+#ifndef cpu_guest_has_dyn_msa
+#define cpu_guest_has_dyn_msa  (cpu_data[0].guest.ases_dyn & MIPS_ASE_MSA)
+#endif
+#ifndef cpu_guest_has_dyn_maar
+#define cpu_guest_has_dyn_maar (cpu_data[0].guest.options_dyn & MIPS_CPU_MAAR)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
index af12c1f9f1a893d8bc266035e6665bf3b36a52a0..edbe2734a1bf07ff6bef041881282d0ab968fb7c 100644 (file)
@@ -28,6 +28,15 @@ struct cache_desc {
        unsigned char flags;    /* Flags describing cache properties */
 };
 
+struct guest_info {
+       unsigned long           ases;
+       unsigned long           ases_dyn;
+       unsigned long long      options;
+       unsigned long long      options_dyn;
+       u8                      conf;
+       u8                      kscratch_mask;
+};
+
 /*
  * Flag definitions
  */
@@ -40,6 +49,9 @@ struct cache_desc {
 
 struct cpuinfo_mips {
        unsigned long           asid_cache;
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       unsigned long           asid_mask;
+#endif
 
        /*
         * Capability and feature descriptor structure for MIPS CPU
@@ -60,6 +72,7 @@ struct cpuinfo_mips {
        int                     tlbsizeftlbways;
        struct cache_desc       icache; /* Primary I-cache */
        struct cache_desc       dcache; /* Primary D or combined I/D cache */
+       struct cache_desc       vcache; /* Victim cache, between pcache and scache */
        struct cache_desc       scache; /* Secondary cache */
        struct cache_desc       tcache; /* Tertiary/split secondary cache */
        int                     srsets; /* Shadow register sets */
@@ -68,7 +81,7 @@ struct cpuinfo_mips {
 #ifdef CONFIG_64BIT
        int                     vmbits; /* Virtual memory size in bits */
 #endif
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
        /*
         * There is not necessarily a 1:1 mapping of VPE num to CPU number
         * in particular on multi-core systems.
@@ -91,6 +104,11 @@ struct cpuinfo_mips {
         * htw_start/htw_stop calls
         */
        unsigned int            htw_seq;
+
+       /* VZ & Guest features */
+       struct guest_info       guest;
+       unsigned int            gtoffset_mask;
+       unsigned int            guestid_mask;
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
 extern struct cpuinfo_mips cpu_data[];
@@ -125,10 +143,31 @@ struct proc_cpuinfo_notifier_args {
        unsigned long n;
 };
 
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
 # define cpu_vpe_id(cpuinfo)   ((cpuinfo)->vpe_id)
 #else
 # define cpu_vpe_id(cpuinfo)   ({ (void)cpuinfo; 0; })
 #endif
 
+static inline unsigned long cpu_asid_inc(void)
+{
+       return 1 << CONFIG_MIPS_ASID_SHIFT;
+}
+
+static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo)
+{
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       return cpuinfo->asid_mask;
+#endif
+       return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT;
+}
+
+static inline void set_cpu_asid_mask(struct cpuinfo_mips *cpuinfo,
+                                    unsigned long asid_mask)
+{
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       cpuinfo->asid_mask = asid_mask;
+#endif
+}
+
 #endif /* __ASM_CPU_INFO_H */
index abee2bfd10dc1dce791ae5691417303d58b08ce6..fbe1881f28fca71d6a4f5e6306357e3c14818e98 100644 (file)
@@ -77,8 +77,13 @@ static inline int __pure __get_cpu_type(const int cpu_type)
         */
 #endif
 
+#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R6
+       case CPU_M6250:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
        case CPU_I6400:
+       case CPU_P6600:
 #endif
 
 #ifdef CONFIG_SYS_HAS_CPU_R3000
index a97ca97285ecf1dd897c9c7a9610209e15ad70c7..f672df8b26d0126c7dd9ffd783fad8102fd1d24c 100644 (file)
@@ -42,6 +42,7 @@
 #define PRID_COMP_LEXRA                0x0b0000
 #define PRID_COMP_NETLOGIC     0x0c0000
 #define PRID_COMP_CAVIUM       0x0d0000
+#define PRID_COMP_LOONGSON     0x140000
 #define PRID_COMP_INGENIC_D0   0xd00000        /* JZ4740, JZ4750 */
 #define PRID_COMP_INGENIC_D1   0xd10000        /* JZ4770, JZ4775 */
 #define PRID_COMP_INGENIC_E1   0xe10000        /* JZ4780 */
 #define PRID_IMP_INTERAPTIV_MP 0xa100
 #define PRID_IMP_PROAPTIV_UP   0xa200
 #define PRID_IMP_PROAPTIV_MP   0xa300
+#define PRID_IMP_P6600         0xa400
 #define PRID_IMP_M5150         0xa700
 #define PRID_IMP_P5600         0xa800
 #define PRID_IMP_I6400         0xa900
+#define PRID_IMP_M6250         0xab00
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
 #define PRID_IMP_CAVIUM_CNF71XX 0x9400
 #define PRID_IMP_CAVIUM_CN78XX 0x9500
 #define PRID_IMP_CAVIUM_CN70XX 0x9600
+#define PRID_IMP_CAVIUM_CN73XX 0x9700
+#define PRID_IMP_CAVIUM_CNF75XX 0x9800
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_*
 #define PRID_REV_LOONGSON1B    0x0020
 #define PRID_REV_LOONGSON2E    0x0002
 #define PRID_REV_LOONGSON2F    0x0003
-#define PRID_REV_LOONGSON3A    0x0005
+#define PRID_REV_LOONGSON3A_R1 0x0005
 #define PRID_REV_LOONGSON3B_R1 0x0006
 #define PRID_REV_LOONGSON3B_R2 0x0007
+#define PRID_REV_LOONGSON3A_R2 0x0008
 
 /*
  * Older processors used to encode processor version and revision in two
@@ -307,8 +313,8 @@ 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_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150,
-       CPU_I6400,
+       CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K,
+       CPU_M5150, CPU_I6400, CPU_P6600, CPU_M6250,
 
        /*
         * MIPS64 class processors
@@ -345,49 +351,69 @@ enum cpu_type_enum {
        MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2 | \
        MIPS_CPU_ISA_M64R6)
 
+/*
+ * Private version of BIT_ULL() to escape include file recursion hell.
+ * We soon will have to switch to another mechanism that will work with
+ * more than 64 bits anyway.
+ */
+#define MBIT_ULL(bit)          (1ULL << (bit))
+
 /*
  * CPU Option encodings
  */
-#define MIPS_CPU_TLB           0x00000001ull /* CPU has TLB */
-#define MIPS_CPU_4KEX          0x00000002ull /* "R4K" exception model */
-#define MIPS_CPU_3K_CACHE      0x00000004ull /* R3000-style caches */
-#define MIPS_CPU_4K_CACHE      0x00000008ull /* R4000-style caches */
-#define MIPS_CPU_TX39_CACHE    0x00000010ull /* TX3900-style caches */
-#define MIPS_CPU_FPU           0x00000020ull /* CPU has FPU */
-#define MIPS_CPU_32FPR         0x00000040ull /* 32 dbl. prec. FP registers */
-#define MIPS_CPU_COUNTER       0x00000080ull /* Cycle count/compare */
-#define MIPS_CPU_WATCH         0x00000100ull /* watchpoint registers */
-#define MIPS_CPU_DIVEC         0x00000200ull /* dedicated interrupt vector */
-#define MIPS_CPU_VCE           0x00000400ull /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX_P  0x00000800ull /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_CACHE_CDEX_S  0x00001000ull /* ... same for seconary cache ... */
-#define MIPS_CPU_MCHECK                0x00002000ull /* Machine check exception */
-#define MIPS_CPU_EJTAG         0x00004000ull /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX       0x00008000ull /* no FPU exception */
-#define MIPS_CPU_LLSC          0x00010000ull /* CPU has ll/sc instructions */
-#define MIPS_CPU_INCLUSIVE_CACHES      0x00020000ull /* P-cache subset enforced */
-#define MIPS_CPU_PREFETCH      0x00040000ull /* CPU has usable prefetch */
-#define MIPS_CPU_VINT          0x00080000ull /* CPU supports MIPSR2 vectored interrupts */
-#define MIPS_CPU_VEIC          0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */
-#define MIPS_CPU_ULRI          0x00200000ull /* CPU has ULRI feature */
-#define MIPS_CPU_PCI           0x00400000ull /* CPU has Perf Ctr Int indicator */
-#define MIPS_CPU_RIXI          0x00800000ull /* CPU has TLB Read/eXec Inhibit */
-#define MIPS_CPU_MICROMIPS     0x01000000ull /* CPU has microMIPS capability */
-#define MIPS_CPU_TLBINV                0x02000000ull /* CPU supports TLBINV/F */
-#define MIPS_CPU_SEGMENTS      0x04000000ull /* CPU supports Segmentation Control registers */
-#define MIPS_CPU_EVA           0x80000000ull /* CPU supports Enhanced Virtual Addressing */
-#define MIPS_CPU_HTW           0x100000000ull /* CPU support Hardware Page Table Walker */
-#define MIPS_CPU_RIXIEX                0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
-#define MIPS_CPU_MAAR          0x400000000ull /* MAAR(I) registers are present */
-#define MIPS_CPU_FRE           0x800000000ull /* FRE & UFE bits implemented */
-#define MIPS_CPU_RW_LLB                0x1000000000ull /* LLADDR/LLB writes are allowed */
-#define MIPS_CPU_XPA           0x2000000000ull /* CPU supports Extended Physical Addressing */
-#define MIPS_CPU_CDMM          0x4000000000ull /* CPU has Common Device Memory Map */
-#define MIPS_CPU_BP_GHIST      0x8000000000ull /* R12K+ Branch Prediction Global History */
-#define MIPS_CPU_SP            0x10000000000ull /* Small (1KB) page support */
-#define MIPS_CPU_FTLB          0x20000000000ull /* CPU has Fixed-page-size TLB */
-#define MIPS_CPU_NAN_LEGACY    0x40000000000ull /* Legacy NaN implemented */
-#define MIPS_CPU_NAN_2008      0x80000000000ull /* 2008 NaN implemented */
+#define MIPS_CPU_TLB           MBIT_ULL( 0)    /* CPU has TLB */
+#define MIPS_CPU_4KEX          MBIT_ULL( 1)    /* "R4K" exception model */
+#define MIPS_CPU_3K_CACHE      MBIT_ULL( 2)    /* R3000-style caches */
+#define MIPS_CPU_4K_CACHE      MBIT_ULL( 3)    /* R4000-style caches */
+#define MIPS_CPU_TX39_CACHE    MBIT_ULL( 4)    /* TX3900-style caches */
+#define MIPS_CPU_FPU           MBIT_ULL( 5)    /* CPU has FPU */
+#define MIPS_CPU_32FPR         MBIT_ULL( 6)    /* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER       MBIT_ULL( 7)    /* Cycle count/compare */
+#define MIPS_CPU_WATCH         MBIT_ULL( 8)    /* watchpoint registers */
+#define MIPS_CPU_DIVEC         MBIT_ULL( 9)    /* dedicated interrupt vector */
+#define MIPS_CPU_VCE           MBIT_ULL(10)    /* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX_P  MBIT_ULL(11)    /* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S  MBIT_ULL(12)    /* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK                MBIT_ULL(13)    /* Machine check exception */
+#define MIPS_CPU_EJTAG         MBIT_ULL(14)    /* EJTAG exception */
+#define MIPS_CPU_NOFPUEX       MBIT_ULL(15)    /* no FPU exception */
+#define MIPS_CPU_LLSC          MBIT_ULL(16)    /* CPU has ll/sc instructions */
+#define MIPS_CPU_INCLUSIVE_CACHES      MBIT_ULL(17)    /* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH      MBIT_ULL(18)    /* CPU has usable prefetch */
+#define MIPS_CPU_VINT          MBIT_ULL(19)    /* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC          MBIT_ULL(20)    /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI          MBIT_ULL(21)    /* CPU has ULRI feature */
+#define MIPS_CPU_PCI           MBIT_ULL(22)    /* CPU has Perf Ctr Int indicator */
+#define MIPS_CPU_RIXI          MBIT_ULL(23)    /* CPU has TLB Read/eXec Inhibit */
+#define MIPS_CPU_MICROMIPS     MBIT_ULL(24)    /* CPU has microMIPS capability */
+#define MIPS_CPU_TLBINV                MBIT_ULL(25)    /* CPU supports TLBINV/F */
+#define MIPS_CPU_SEGMENTS      MBIT_ULL(26)    /* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA           MBIT_ULL(27)    /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_HTW           MBIT_ULL(28)    /* CPU support Hardware Page Table Walker */
+#define MIPS_CPU_RIXIEX                MBIT_ULL(29)    /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
+#define MIPS_CPU_MAAR          MBIT_ULL(30)    /* MAAR(I) registers are present */
+#define MIPS_CPU_FRE           MBIT_ULL(31)    /* FRE & UFE bits implemented */
+#define MIPS_CPU_RW_LLB                MBIT_ULL(32)    /* LLADDR/LLB writes are allowed */
+#define MIPS_CPU_LPA           MBIT_ULL(33)    /* CPU supports Large Physical Addressing */
+#define MIPS_CPU_CDMM          MBIT_ULL(34)    /* CPU has Common Device Memory Map */
+#define MIPS_CPU_BP_GHIST      MBIT_ULL(35)    /* R12K+ Branch Prediction Global History */
+#define MIPS_CPU_SP            MBIT_ULL(36)    /* Small (1KB) page support */
+#define MIPS_CPU_FTLB          MBIT_ULL(37)    /* CPU has Fixed-page-size TLB */
+#define MIPS_CPU_NAN_LEGACY    MBIT_ULL(38)    /* Legacy NaN implemented */
+#define MIPS_CPU_NAN_2008      MBIT_ULL(39)    /* 2008 NaN implemented */
+#define MIPS_CPU_VP            MBIT_ULL(40)    /* MIPSr6 Virtual Processors (multi-threading) */
+#define MIPS_CPU_LDPTE         MBIT_ULL(41)    /* CPU has ldpte/lddir instructions */
+#define MIPS_CPU_MVH           MBIT_ULL(42)    /* CPU supports MFHC0/MTHC0 */
+#define MIPS_CPU_EBASE_WG      MBIT_ULL(43)    /* CPU has EBase.WG */
+#define MIPS_CPU_BADINSTR      MBIT_ULL(44)    /* CPU has BadInstr register */
+#define MIPS_CPU_BADINSTRP     MBIT_ULL(45)    /* CPU has BadInstrP register */
+#define MIPS_CPU_CTXTC         MBIT_ULL(46)    /* CPU has [X]ConfigContext registers */
+#define MIPS_CPU_PERF          MBIT_ULL(47)    /* CPU has MIPS performance counters */
+#define MIPS_CPU_GUESTCTL0EXT  MBIT_ULL(48)    /* CPU has VZ GuestCtl0Ext register */
+#define MIPS_CPU_GUESTCTL1     MBIT_ULL(49)    /* CPU has VZ GuestCtl1 register */
+#define MIPS_CPU_GUESTCTL2     MBIT_ULL(50)    /* CPU has VZ GuestCtl2 register */
+#define MIPS_CPU_GUESTID       MBIT_ULL(51)    /* CPU uses VZ ASE GuestID feature */
+#define MIPS_CPU_DRG           MBIT_ULL(52)    /* CPU has VZ Direct Root to Guest (DRG) */
 
 /*
  * CPU ASE encodings
@@ -401,5 +427,6 @@ enum cpu_type_enum {
 #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 */
+#define MIPS_ASE_DSP3          0x00000200 /* Signal Processing ASE Rev 3*/
 
 #endif /* _ASM_CPU_H */
index e090fc388e02483faf1291e2f4844f823aec5bc2..f5f45717968e6103e54509beeb88c338a245a3d4 100644 (file)
  */
 #define R_MIPS_CALLHI16                30
 #define R_MIPS_CALLLO16                31
+/*
+ * Introduced for MIPSr6.
+ */
+#define R_MIPS_PC21_S2         60
+#define R_MIPS_PC26_S2         61
 /*
  * This range is reserved for vendor specific relocations.
  */
 #define SHF_MIPS_NAMES         0x02000000
 #define SHF_MIPS_NODUPES       0x01000000
 
-#ifndef ELF_ARCH
-/* ELF register definitions */
-#define ELF_NGREG      45
-#define ELF_NFPREG     33
-
-typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef double elf_fpreg_t;
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+#define MIPS_ABI_FP_ANY                0       /* FP ABI doesn't matter */
+#define MIPS_ABI_FP_DOUBLE     1       /* -mdouble-float */
+#define MIPS_ABI_FP_SINGLE     2       /* -msingle-float */
+#define MIPS_ABI_FP_SOFT       3       /* -msoft-float */
+#define MIPS_ABI_FP_OLD_64     4       /* -mips32r2 -mfp64 */
+#define MIPS_ABI_FP_XX         5       /* -mfpxx */
+#define MIPS_ABI_FP_64         6       /* -mips32r2 -mfp64 */
+#define MIPS_ABI_FP_64A                7       /* -mips32r2 -mfp64 -mno-odd-spreg */
 
 struct mips_elf_abiflags_v0 {
        uint16_t version;       /* Version of flags structure */
@@ -196,16 +199,54 @@ struct mips_elf_abiflags_v0 {
        uint32_t flags2;
 };
 
-#define MIPS_ABI_FP_ANY                0       /* FP ABI doesn't matter */
-#define MIPS_ABI_FP_DOUBLE     1       /* -mdouble-float */
-#define MIPS_ABI_FP_SINGLE     2       /* -msingle-float */
-#define MIPS_ABI_FP_SOFT       3       /* -msoft-float */
-#define MIPS_ABI_FP_OLD_64     4       /* -mips32r2 -mfp64 */
-#define MIPS_ABI_FP_XX         5       /* -mfpxx */
-#define MIPS_ABI_FP_64         6       /* -mips32r2 -mfp64 */
-#define MIPS_ABI_FP_64A                7       /* -mips32r2 -mfp64 -mno-odd-spreg */
+#ifndef ELF_ARCH
+/* ELF register definitions */
+#define ELF_NGREG      45
+#define ELF_NFPREG     33
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #ifdef CONFIG_32BIT
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch elfo32_check_arch
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS32
+
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch elfn64_check_arch
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS64
+
+#endif /* CONFIG_64BIT */
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#ifdef __MIPSEB__
+#define ELF_DATA       ELFDATA2MSB
+#elif defined(__MIPSEL__)
+#define ELF_DATA       ELFDATA2LSB
+#endif
+#define ELF_ARCH       EM_MIPS
+
+#endif /* !defined(ELF_ARCH) */
 
 /*
  * In order to be sure that we don't attempt to execute an O32 binary which
@@ -219,10 +260,15 @@ struct mips_elf_abiflags_v0 {
 # define __MIPS_O32_FP64_MUST_BE_ZERO  EF_MIPS_FP64
 #endif
 
+#define mips_elf_check_machine(x) ((x)->e_machine == EM_MIPS)
+
+#define vmcore_elf32_check_arch mips_elf_check_machine
+#define vmcore_elf64_check_arch mips_elf_check_machine
+
 /*
- * This is used to ensure we don't load something for the wrong architecture.
+ * Return non-zero if HDR identifies an o32 ELF binary.
  */
-#define elf_check_arch(hdr)                                            \
+#define elfo32_check_arch(hdr)                                         \
 ({                                                                     \
        int __res = 1;                                                  \
        struct elfhdr *__h = (hdr);                                     \
@@ -243,17 +289,9 @@ struct mips_elf_abiflags_v0 {
 })
 
 /*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS      ELFCLASS32
-
-#endif /* CONFIG_32BIT */
-
-#ifdef CONFIG_64BIT
-/*
- * This is used to ensure we don't load something for the wrong architecture.
+ * Return non-zero if HDR identifies an n64 ELF binary.
  */
-#define elf_check_arch(hdr)                                            \
+#define elfn64_check_arch(hdr)                                         \
 ({                                                                     \
        int __res = 1;                                                  \
        struct elfhdr *__h = (hdr);                                     \
@@ -267,28 +305,23 @@ struct mips_elf_abiflags_v0 {
 })
 
 /*
- * These are used to set parameters in the core dumps.
+ * Return non-zero if HDR identifies an n32 ELF binary.
  */
-#define ELF_CLASS      ELFCLASS64
-
-#endif /* CONFIG_64BIT */
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#ifdef __MIPSEB__
-#define ELF_DATA       ELFDATA2MSB
-#elif defined(__MIPSEL__)
-#define ELF_DATA       ELFDATA2LSB
-#endif
-#define ELF_ARCH       EM_MIPS
-
-#endif /* !defined(ELF_ARCH) */
-
-#define mips_elf_check_machine(x) ((x)->e_machine == EM_MIPS)
-
-#define vmcore_elf32_check_arch mips_elf_check_machine
-#define vmcore_elf64_check_arch mips_elf_check_machine
+#define elfn32_check_arch(hdr)                                         \
+({                                                                     \
+       int __res = 1;                                                  \
+       struct elfhdr *__h = (hdr);                                     \
+                                                                       \
+       if (!mips_elf_check_machine(__h))                               \
+               __res = 0;                                              \
+       if (__h->e_ident[EI_CLASS] != ELFCLASS32)                       \
+               __res = 0;                                              \
+       if (((__h->e_flags & EF_MIPS_ABI2) == 0) ||                     \
+           ((__h->e_flags & EF_MIPS_ABI) != 0))                        \
+               __res = 0;                                              \
+                                                                       \
+       __res;                                                          \
+})
 
 struct mips_abi;
 
@@ -300,17 +333,16 @@ extern struct mips_abi mips_abi_n32;
 
 #define SET_PERSONALITY2(ex, state)                                    \
 do {                                                                   \
-       if (personality(current->personality) != PER_LINUX)             \
-               set_personality(PER_LINUX);                             \
-                                                                       \
        clear_thread_flag(TIF_HYBRID_FPREGS);                           \
        set_thread_flag(TIF_32BIT_FPREGS);                              \
                                                                        \
-       mips_set_personality_fp(state);                                 \
-                                                                       \
        current->thread.abi = &mips_abi;                                \
                                                                        \
+       mips_set_personality_fp(state);                                 \
        mips_set_personality_nan(state);                                \
+                                                                       \
+       if (personality(current->personality) != PER_LINUX)             \
+               set_personality(PER_LINUX);                             \
 } while (0)
 
 #endif /* CONFIG_32BIT */
@@ -321,6 +353,7 @@ do {                                                                        \
 #define __SET_PERSONALITY32_N32()                                      \
        do {                                                            \
                set_thread_flag(TIF_32BIT_ADDR);                        \
+                                                                       \
                current->thread.abi = &mips_abi_n32;                    \
        } while (0)
 #else
@@ -336,9 +369,9 @@ do {                                                                        \
                clear_thread_flag(TIF_HYBRID_FPREGS);                   \
                set_thread_flag(TIF_32BIT_FPREGS);                      \
                                                                        \
-               mips_set_personality_fp(state);                         \
-                                                                       \
                current->thread.abi = &mips_abi_32;                     \
+                                                                       \
+               mips_set_personality_fp(state);                         \
        } while (0)
 #else
 #define __SET_PERSONALITY32_O32(ex, state)                             \
index 7b99efd310748dbfe12c29459ffdd5e4137a2bf8..dbb1eb6e284f1e67880fadee3c8aed696164c31d 100644 (file)
@@ -22,7 +22,8 @@
 /*
  * TLB hazards
  */
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
+#if (defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)) && \
+       !defined(CONFIG_CPU_CAVIUM_OCTEON) && !defined(CONFIG_LOONGSON3_ENHANCEMENT)
 
 /*
  * MIPSR2 defines ehb for hazard avoidance
@@ -155,8 +156,8 @@ do {                                                                        \
 } while (0)
 
 #elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
-       defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \
-       defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)
+       defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_LOONGSON3_ENHANCEMENT) || \
+       defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
index 01880b34a209b37dd5b02d759afda543f7989e9a..64f2500d891b279493f422129fcb2093180a2527 100644 (file)
 
 #ifdef __KERNEL__
 
+#include <linux/bug.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
+#include <asm/cpu-features.h>
 #include <asm/kmap_types.h>
 
 /* undef for production */
@@ -50,7 +52,7 @@ extern void *kmap_atomic(struct page *page);
 extern void __kunmap_atomic(void *kvaddr);
 extern void *kmap_atomic_pfn(unsigned long pfn);
 
-#define flush_cache_kmaps()    flush_cache_all()
+#define flush_cache_kmaps()    BUG_ON(cpu_has_dc_aliases)
 
 extern void kmap_init(void);
 
index 2b4dc7ad53b8a32bc139dd33d15cb5bb533f8d85..ecabc00c1e665ae237faf60a10f07599d04a65c3 100644 (file)
@@ -304,10 +304,10 @@ static inline void iounmap(const volatile void __iomem *addr)
 #undef __IS_KSEG1
 }
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-#define war_octeon_io_reorder_wmb()            wmb()
+#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT)
+#define war_io_reorder_wmb()           wmb()
 #else
-#define war_octeon_io_reorder_wmb()            do { } while (0)
+#define war_io_reorder_wmb()           do { } while (0)
 #endif
 
 #define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq)                    \
@@ -318,7 +318,7 @@ static inline void pfx##write##bwlq(type val,                               \
        volatile type *__mem;                                           \
        type __val;                                                     \
                                                                        \
-       war_octeon_io_reorder_wmb();                                    \
+       war_io_reorder_wmb();                                   \
                                                                        \
        __mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem));    \
                                                                        \
@@ -387,7 +387,7 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port)  \
        volatile type *__addr;                                          \
        type __val;                                                     \
                                                                        \
-       war_octeon_io_reorder_wmb();                                    \
+       war_io_reorder_wmb();                                   \
                                                                        \
        __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
                                                                        \
index 33bd2a06de577ece986977f07c495fd0e3b5daea..8c48d6dd1d7894d59aaade09ef7843695f854b0c 100644 (file)
@@ -18,4 +18,14 @@ static inline struct pt_regs *get_irq_regs(void)
        return current_thread_info()->regs;
 }
 
+static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
+{
+       struct pt_regs *old_regs;
+
+       old_regs = get_irq_regs();
+       current_thread_info()->regs = new_regs;
+
+       return old_regs;
+}
+
 #endif /* __ASM_IRQ_REGS_H */
index 65c351e328cc932af4aedca946ee19f9bd43f8c3..9d3610be2323a1ae885320ffe81cd3577e327872 100644 (file)
@@ -41,7 +41,12 @@ static inline unsigned long arch_local_irq_save(void)
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
+#if defined(CONFIG_CPU_LOONGSON3)
+       "       mfc0    %[flags], $12                                   \n"
+       "       di                                                      \n"
+#else
        "       di      %[flags]                                        \n"
+#endif
        "       andi    %[flags], 1                                     \n"
        "       " __stringify(__irq_disable_hazard) "                   \n"
        "       .set    pop                                             \n"
index f6b12790716c071db8a3ce17971dd146c30025f5..b76e132c87e4b1c74c6472ebfda5858b790f87d5 100644 (file)
@@ -311,17 +311,18 @@ enum emulation_result {
 #define MIPS3_PG_FRAME         0x3fffffc0
 
 #define VPN2_MASK              0xffffe000
+#define KVM_ENTRYHI_ASID       MIPS_ENTRYHI_ASID
 #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_ASID(x)            ((x).tlb_hi & KVM_ENTRYHI_ASID)
 #define TLB_IS_VALID(x, va)    (((va) & (1 << PAGE_SHIFT))             \
                                 ? ((x).tlb_lo1 & MIPS3_PG_V)           \
                                 : ((x).tlb_lo0 & MIPS3_PG_V))
 #define TLB_HI_VPN2_HIT(x, y)  ((TLB_VPN2(x) & ~(x).tlb_mask) ==       \
                                 ((y) & VPN2_MASK & ~(x).tlb_mask))
 #define TLB_HI_ASID_HIT(x, y)  (TLB_IS_GLOBAL(x) ||                    \
-                                TLB_ASID(x) == ((y) & ASID_MASK))
+                                TLB_ASID(x) == ((y) & KVM_ENTRYHI_ASID))
 
 struct kvm_mips_tlb {
        long tlb_mask;
diff --git a/arch/mips/include/asm/llsc.h b/arch/mips/include/asm/llsc.h
new file mode 100644 (file)
index 0000000..c6d17d1
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ * Macros for 32/64-bit neutral inline assembler
+ */
+
+#ifndef __ASM_LLSC_H
+#define __ASM_LLSC_H
+
+#if _MIPS_SZLONG == 32
+#define SZLONG_LOG 5
+#define SZLONG_MASK 31UL
+#define __LL           "ll     "
+#define __SC           "sc     "
+#define __INS          "ins    "
+#define __EXT          "ext    "
+#elif _MIPS_SZLONG == 64
+#define SZLONG_LOG 6
+#define SZLONG_MASK 63UL
+#define __LL           "lld    "
+#define __SC           "scd    "
+#define __INS          "dins   "
+#define __EXT          "dext   "
+#endif
+
+#endif /* __ASM_LLSC_H  */
diff --git a/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h
new file mode 100644 (file)
index 0000000..fa0583e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H
+
+/* Invariants across all BMIPS processors */
+#define cpu_has_vtag_icache            0
+#define cpu_icache_snoops_remote_store 1
+
+/* Processor ISA compatibility is MIPS32R1 */
+#define cpu_has_mips32r1               1
+#define cpu_has_mips32r2               0
+#define cpu_has_mips64r1               0
+#define cpu_has_mips64r2               0
+
+#endif /* __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-bmips/ioremap.h b/arch/mips/include/asm/mach-bmips/ioremap.h
new file mode 100644 (file)
index 0000000..29c7a7b
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __ASM_MACH_BMIPS_IOREMAP_H
+#define __ASM_MACH_BMIPS_IOREMAP_H
+
+#include <linux/types.h>
+
+static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
+{
+       return phys_addr;
+}
+
+static inline int is_bmips_internal_registers(phys_addr_t offset)
+{
+       if (offset >= 0xfff80000)
+               return 1;
+
+       return 0;
+}
+
+static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
+                                        unsigned long flags)
+{
+       if (is_bmips_internal_registers(offset))
+               return (void __iomem *)offset;
+
+       return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+       return is_bmips_internal_registers((unsigned long)addr);
+}
+
+#endif /* __ASM_MACH_BMIPS_IOREMAP_H */
index 32cfbe6a191be8defd37fc373dc5a6cf951f3852..073b8bfbb3b3f16525df19d9802b2d32897a9bcd 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/platform_device.h>
 
-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;
index 98d6a2f14aafcfa4f89f0db644f2351f8b8ad453..7023883ca50f843efe4d8321f35f64ce2b89eef0 100644 (file)
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_FALCON_H__
index 4e5ae6523cb421158e6ddcc0db24e2b3afd8ee73..8064d7a4b33d7ae88d0889fa32ab0e92c5197c8b 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 #ifndef _LANTIQ_H__
 #define _LANTIQ_H__
index e23bf7c9a2d0782fa4827ab2297de1a033eb6fdd..17d2fdcdaef448bdd0d425526d7c01b00e02afc4 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LANTIQ_PLATFORM_H__
index a1471d2dd0d24b7802ef3037a4b8cdac1a4c47e8..83e5f03cccb51b7bf5009e9355cc888e29ce8c1d 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef __LANTIQ_IRQ_H
index 5eadfe5825296fbf70933c0ceee9515b0f306d20..141076325307ecfd748d36e76ff008aa76366b5c 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LANTIQ_XWAY_IRQ_H__
index dd6005b75e0c0bb594e657ede11df74b21776852..f87310755319b236367252474f6f09b068c137a7 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_XWAY_H__
index 5f8693d5ab126a843429a69eb0ba2eed4742d6af..4901833498f7e3878b458d23afb876e7812a95f1 100644 (file)
@@ -12,7 +12,7 @@
  *   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) 2011 John Crispin <blogic@openwrt.org>
+ *   Copyright (C) 2011 John Crispin <john@phrozen.org>
  */
 
 #ifndef LTQ_DMA_H__
index 6843fa1a608de8db0a29160e8871215f26e9d97a..2f1ecb08122341fa3edfafabb754311b057a2e55 100644 (file)
@@ -9,7 +9,6 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_CPUFREQ_H
 #define __ASM_MACH_LOONGSON32_CPUFREQ_H
 
diff --git a/arch/mips/include/asm/mach-loongson32/dma.h b/arch/mips/include/asm/mach-loongson32/dma.h
new file mode 100644 (file)
index 0000000..ad1dec7
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 NAND platform support.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_DMA_H
+#define __ASM_MACH_LOONGSON32_DMA_H
+
+#define LS1X_DMA_CHANNEL0      0
+#define LS1X_DMA_CHANNEL1      1
+#define LS1X_DMA_CHANNEL2      2
+
+struct plat_ls1x_dma {
+       int nr_channels;
+};
+
+extern struct plat_ls1x_dma ls1b_dma_pdata;
+
+#endif /* __ASM_MACH_LOONGSON32_DMA_H */
index 0d35b994e8d20248b6d8e0ce70afcd2ac103314a..c1c744197de498e4c38be02b18f4732f789ae4ea 100644 (file)
@@ -9,7 +9,6 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_IRQ_H
 #define __ASM_MACH_LOONGSON32_IRQ_H
 
index 12aa129aad807129be51244474e96cabf097a2bf..978f6df8970a38946ddd5afcdb21d0ba5f3f9312 100644 (file)
@@ -9,7 +9,6 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H
 #define __ASM_MACH_LOONGSON32_LOONGSON1_H
 
@@ -18,6 +17,9 @@
 /* Loongson 1 Register Bases */
 #define LS1X_MUX_BASE                  0x1fd00420
 #define LS1X_INTC_BASE                 0x1fd01040
+#define LS1X_GPIO0_BASE                        0x1fd010c0
+#define LS1X_GPIO1_BASE                        0x1fd010c4
+#define LS1X_DMAC_BASE                 0x1fd01160
 #define LS1X_EHCI_BASE                 0x1fe00000
 #define LS1X_OHCI_BASE                 0x1fe08000
 #define LS1X_GMAC0_BASE                        0x1fe10000
diff --git a/arch/mips/include/asm/mach-loongson32/nand.h b/arch/mips/include/asm/mach-loongson32/nand.h
new file mode 100644 (file)
index 0000000..e274912
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 NAND platform support.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_NAND_H
+#define __ASM_MACH_LOONGSON32_NAND_H
+
+#include <linux/dmaengine.h>
+#include <linux/mtd/partitions.h>
+
+struct plat_ls1x_nand {
+       struct mtd_partition *parts;
+       unsigned int nr_parts;
+
+       int hold_cycle;
+       int wait_cycle;
+};
+
+extern struct plat_ls1x_nand ls1b_nand_pdata;
+
+bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param);
+
+#endif /* __ASM_MACH_LOONGSON32_NAND_H */
index c32f03f3f72cefef04df672243e052069702444b..672531aa9bef0a20488f578682e27ae81d113d61 100644 (file)
@@ -7,20 +7,28 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_PLATFORM_H
 #define __ASM_MACH_LOONGSON32_PLATFORM_H
 
 #include <linux/platform_device.h>
 
+#include <dma.h>
+#include <nand.h>
+
 extern struct platform_device ls1x_uart_pdev;
 extern struct platform_device ls1x_cpufreq_pdev;
+extern struct platform_device ls1x_dma_pdev;
 extern struct platform_device ls1x_eth0_pdev;
 extern struct platform_device ls1x_eth1_pdev;
 extern struct platform_device ls1x_ehci_pdev;
+extern struct platform_device ls1x_gpio0_pdev;
+extern struct platform_device ls1x_gpio1_pdev;
+extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
 
-extern void __init ls1x_clk_init(void);
-extern void __init ls1x_serial_setup(struct platform_device *pdev);
+void __init ls1x_clk_init(void);
+void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
+void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
index 1f5a715ac8418c18930a34ed60694f48f548a032..4d56fc38f0c47be5604a6688754528d43c803240 100644 (file)
 #define LS1X_CLK_PLL_DIV               LS1X_CLK_REG(0x4)
 
 /* Clock PLL Divisor Register Bits */
-#define DIV_DC_EN                      (0x1 << 31)
-#define DIV_DC_RST                     (0x1 << 30)
-#define DIV_CPU_EN                     (0x1 << 25)
-#define DIV_CPU_RST                    (0x1 << 24)
-#define DIV_DDR_EN                     (0x1 << 19)
-#define DIV_DDR_RST                    (0x1 << 18)
-#define RST_DC_EN                      (0x1 << 5)
-#define RST_DC                         (0x1 << 4)
-#define RST_DDR_EN                     (0x1 << 3)
-#define RST_DDR                                (0x1 << 2)
-#define RST_CPU_EN                     (0x1 << 1)
-#define RST_CPU                                0x1
+#define DIV_DC_EN                      BIT(31)
+#define DIV_DC_RST                     BIT(30)
+#define DIV_CPU_EN                     BIT(25)
+#define DIV_CPU_RST                    BIT(24)
+#define DIV_DDR_EN                     BIT(19)
+#define DIV_DDR_RST                    BIT(18)
+#define RST_DC_EN                      BIT(5)
+#define RST_DC                         BIT(4)
+#define RST_DDR_EN                     BIT(3)
+#define RST_DDR                                BIT(2)
+#define RST_CPU_EN                     BIT(1)
+#define RST_CPU                                BIT(0)
 
 #define DIV_DC_SHIFT                   26
 #define DIV_CPU_SHIFT                  20
index 8302d92f2da2ceae8cbe692bf748823f71d8c489..7c394f93cb9e381adb5b1a813cc1745383e80532 100644 (file)
 #define LS1X_MUX_CTRL1                 LS1X_MUX_REG(0x4)
 
 /* MUX CTRL0 Register Bits */
-#define UART0_USE_PWM23                        (0x1 << 28)
-#define UART0_USE_PWM01                        (0x1 << 27)
-#define UART1_USE_LCD0_5_6_11          (0x1 << 26)
-#define I2C2_USE_CAN1                  (0x1 << 25)
-#define I2C1_USE_CAN0                  (0x1 << 24)
-#define NAND3_USE_UART5                        (0x1 << 23)
-#define NAND3_USE_UART4                        (0x1 << 22)
-#define NAND3_USE_UART1_DAT            (0x1 << 21)
-#define NAND3_USE_UART1_CTS            (0x1 << 20)
-#define NAND3_USE_PWM23                        (0x1 << 19)
-#define NAND3_USE_PWM01                        (0x1 << 18)
-#define NAND2_USE_UART5                        (0x1 << 17)
-#define NAND2_USE_UART4                        (0x1 << 16)
-#define NAND2_USE_UART1_DAT            (0x1 << 15)
-#define NAND2_USE_UART1_CTS            (0x1 << 14)
-#define NAND2_USE_PWM23                        (0x1 << 13)
-#define NAND2_USE_PWM01                        (0x1 << 12)
-#define NAND1_USE_UART5                        (0x1 << 11)
-#define NAND1_USE_UART4                        (0x1 << 10)
-#define NAND1_USE_UART1_DAT            (0x1 << 9)
-#define NAND1_USE_UART1_CTS            (0x1 << 8)
-#define NAND1_USE_PWM23                        (0x1 << 7)
-#define NAND1_USE_PWM01                        (0x1 << 6)
-#define GMAC1_USE_UART1                        (0x1 << 4)
-#define GMAC1_USE_UART0                        (0x1 << 3)
-#define LCD_USE_UART0_DAT              (0x1 << 2)
-#define LCD_USE_UART15                 (0x1 << 1)
-#define LCD_USE_UART0                  0x1
+#define UART0_USE_PWM23                        BIT(28)
+#define UART0_USE_PWM01                        BIT(27)
+#define UART1_USE_LCD0_5_6_11          BIT(26)
+#define I2C2_USE_CAN1                  BIT(25)
+#define I2C1_USE_CAN0                  BIT(24)
+#define NAND3_USE_UART5                        BIT(23)
+#define NAND3_USE_UART4                        BIT(22)
+#define NAND3_USE_UART1_DAT            BIT(21)
+#define NAND3_USE_UART1_CTS            BIT(20)
+#define NAND3_USE_PWM23                        BIT(19)
+#define NAND3_USE_PWM01                        BIT(18)
+#define NAND2_USE_UART5                        BIT(17)
+#define NAND2_USE_UART4                        BIT(16)
+#define NAND2_USE_UART1_DAT            BIT(15)
+#define NAND2_USE_UART1_CTS            BIT(14)
+#define NAND2_USE_PWM23                        BIT(13)
+#define NAND2_USE_PWM01                        BIT(12)
+#define NAND1_USE_UART5                        BIT(11)
+#define NAND1_USE_UART4                        BIT(10)
+#define NAND1_USE_UART1_DAT            BIT(9)
+#define NAND1_USE_UART1_CTS            BIT(8)
+#define NAND1_USE_PWM23                        BIT(7)
+#define NAND1_USE_PWM01                        BIT(6)
+#define GMAC1_USE_UART1                        BIT(4)
+#define GMAC1_USE_UART0                        BIT(3)
+#define LCD_USE_UART0_DAT              BIT(2)
+#define LCD_USE_UART15                 BIT(1)
+#define LCD_USE_UART0                  BIT(0)
 
 /* MUX CTRL1 Register Bits */
-#define USB_RESET                      (0x1 << 31)
-#define SPI1_CS_USE_PWM01              (0x1 << 24)
-#define SPI1_USE_CAN                   (0x1 << 23)
-#define DISABLE_DDR_CONFSPACE          (0x1 << 20)
-#define DDR32TO16EN                    (0x1 << 16)
-#define GMAC1_SHUT                     (0x1 << 13)
-#define GMAC0_SHUT                     (0x1 << 12)
-#define USB_SHUT                       (0x1 << 11)
-#define UART1_3_USE_CAN1               (0x1 << 5)
-#define UART1_2_USE_CAN0               (0x1 << 4)
-#define GMAC1_USE_TXCLK                        (0x1 << 3)
-#define GMAC0_USE_TXCLK                        (0x1 << 2)
-#define GMAC1_USE_PWM23                        (0x1 << 1)
-#define GMAC0_USE_PWM01                        0x1
+#define USB_RESET                      BIT(31)
+#define SPI1_CS_USE_PWM01              BIT(24)
+#define SPI1_USE_CAN                   BIT(23)
+#define DISABLE_DDR_CONFSPACE          BIT(20)
+#define DDR32TO16EN                    BIT(16)
+#define GMAC1_SHUT                     BIT(13)
+#define GMAC0_SHUT                     BIT(12)
+#define USB_SHUT                       BIT(11)
+#define UART1_3_USE_CAN1               BIT(5)
+#define UART1_2_USE_CAN0               BIT(4)
+#define GMAC1_USE_TXCLK                        BIT(3)
+#define GMAC0_USE_TXCLK                        BIT(2)
+#define GMAC1_USE_PWM23                        BIT(1)
+#define GMAC0_USE_PWM01                        BIT(0)
 
 #endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */
index 69f174ed13a43d47915b67c8ed32100aa94026bf..4119600ce79a3b8fa17c0ec5734d3edf2c6aa85a 100644 (file)
 #define PWM_CTRL               0xc
 
 /* PWM Control Register Bits */
-#define CNT_RST                        (0x1 << 7)
-#define INT_SR                 (0x1 << 6)
-#define INT_EN                 (0x1 << 5)
-#define PWM_SINGLE             (0x1 << 4)
-#define PWM_OE                 (0x1 << 3)
-#define CNT_EN                 0x1
+#define CNT_RST                        BIT(7)
+#define INT_SR                 BIT(6)
+#define INT_EN                 BIT(5)
+#define PWM_SINGLE             BIT(4)
+#define PWM_OE                 BIT(3)
+#define CNT_EN                 BIT(0)
 
 #endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */
index 98963c2c7be48abf311915cd99fea93f73141cd4..89328a3d44d8556c5ac340dd6c5e22507ecfd66a 100644 (file)
 #ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
 
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#define cpu_scache_line_size() 32
-
-
 #define cpu_has_32fpr          1
 #define cpu_has_3k_cache       0
 #define cpu_has_4k_cache       1
 #define cpu_has_counter                1
 #define cpu_has_dc_aliases     (PAGE_SIZE < 0x4000)
 #define cpu_has_divec          0
-#define cpu_has_dsp            0
-#define cpu_has_dsp2           0
 #define cpu_has_ejtag          0
-#define cpu_has_ic_fills_f_dc  0
 #define cpu_has_inclusive_pcaches      1
 #define cpu_has_llsc           1
 #define cpu_has_mcheck         0
 #define cpu_has_mdmx           0
 #define cpu_has_mips16         0
-#define cpu_has_mips32r2       0
 #define cpu_has_mips3d         0
-#define cpu_has_mips64r2       0
 #define cpu_has_mipsmt         0
-#define cpu_has_prefetch       0
 #define cpu_has_smartmips      0
 #define cpu_has_tlb            1
 #define cpu_has_tx39_cache     0
-#define cpu_has_userlocal      0
 #define cpu_has_vce            0
 #define cpu_has_veic           0
 #define cpu_has_vint           0
 #define cpu_has_watch          1
 #define cpu_has_local_ebase    0
 
-#define cpu_has_wsbh           IS_ENABLED(CONFIG_CPU_LOONGSON3)
+#ifdef CONFIG_CPU_LOONGSON3
+#define cpu_has_wsbh           1
+#define cpu_has_ic_fills_f_dc  1
+#define cpu_hwrena_impl_bits   0xc0000000
+#endif
 
 #endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */
index 3f2f84f6c401f5637b5952477abdea47ab9e657d..8393bc548987d782b9f590b0a9ffecda9fabc61c 100644 (file)
        or      t0, (0x1 << 7)
        mtc0    t0, $16, 3
        /* Set ELPA on LOONGSON3 pagegrain */
-       li      t0, (0x1 << 29)
+       mfc0    t0, $5, 1
+       or      t0, (0x1 << 29)
        mtc0    t0, $5, 1
+#ifdef CONFIG_LOONGSON3_ENHANCEMENT
+       /* Enable STFill Buffer */
+       mfc0    t0, $16, 6
+       or      t0, 0x100
+       mtc0    t0, $16, 6
+#endif
        _ehb
        .set    pop
 #endif
        or      t0, (0x1 << 7)
        mtc0    t0, $16, 3
        /* Set ELPA on LOONGSON3 pagegrain */
-       li      t0, (0x1 << 29)
+       mfc0    t0, $5, 1
+       or      t0, (0x1 << 29)
        mtc0    t0, $5, 1
+#ifdef CONFIG_LOONGSON3_ENHANCEMENT
+       /* Enable STFill Buffer */
+       mfc0    t0, $16, 6
+       or      t0, 0x100
+       mtc0    t0, $16, 6
+#endif
        _ehb
        .set    pop
 #endif
index 455d406e8ddf1667e4c2212aacfe985c2eb08be8..a73350b07fdf0bca66443d480ff2139def92c758 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _MT7620_REGS_H_
@@ -72,6 +72,7 @@
 #define SYSCFG0_DRAM_TYPE_SDRAM                0
 #define SYSCFG0_DRAM_TYPE_DDR1         1
 #define SYSCFG0_DRAM_TYPE_DDR2         2
+#define SYSCFG0_DRAM_TYPE_UNKNOWN      3
 
 #define SYSCFG0_DRAM_TYPE_DDR2_MT7628  0
 #define SYSCFG0_DRAM_TYPE_DDR1_MT7628  1
index 610b61e3f9df125f00ffa26e44534eefd2278ced..a672e06fa5fd065ba492f6da7f45379b28b1e4b5 100644 (file)
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #ifndef _MT7621_REGS_H_
index be106cb2e26d28db930b6d7f9bdfe28c7eee57f5..ba8ac331af0c39110837ae4c983bf76c90eec748 100644 (file)
@@ -3,7 +3,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RT288X_PINMUX_H__
index 4c9fba68c8b2490bfaf98b2f1ec8b2fc77f0ed5f..9df1a53bcb36c60bc082223ff8daa24a7eb4a506 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Ralink SoC register definitions
  *
- *  Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013 John Crispin <john@phrozen.org>
  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
index 03ad716acb42c1e0ebf284b6555c375dab7f1955..25ae1042d57b8cca08c5ba75ff49fda3bf0f1054 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RT288X_REGS_H_
index 2eea79331a14bf040b164ce294e2ce3a0bb99ba7..ac2d65c04b5fb1a9528edf105806687068e0b9c9 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RT305X_REGS_H_
index d4635391c36a28240c9fbdd900d26fdf309e0ca9..9411a4c0bdadf47c78beb30412b8c66df8f51ca5 100644 (file)
@@ -208,6 +208,7 @@ BUILD_CM_RW(l2_config,              MIPS_CM_GCB_OFS + 0x130)
 BUILD_CM_RW(sys_config2,       MIPS_CM_GCB_OFS + 0x150)
 BUILD_CM_RW(l2_pft_control,    MIPS_CM_GCB_OFS + 0x300)
 BUILD_CM_RW(l2_pft_control_b,  MIPS_CM_GCB_OFS + 0x308)
+BUILD_CM_RW(bev_base,          MIPS_CM_GCB_OFS + 0x680)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,  0x00)
@@ -290,8 +291,8 @@ BUILD_CM_Cx_R_(tcid_8_priority,     0x80)
 #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_CPCBASE_SHF            15
+#define CM_GCR_CPC_BASE_CPCBASE_MSK            (_ULCAST_(0x1ffff) << 15)
 #define CM_GCR_CPC_BASE_CPCEN_SHF              0
 #define CM_GCR_CPC_BASE_CPCEN_MSK              (_ULCAST_(0x1) << 0)
 
@@ -461,7 +462,10 @@ static inline unsigned int mips_cm_max_vp_width(void)
        if (mips_cm_revision() >= CM_REV_CM3)
                return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK;
 
-       return smp_num_siblings;
+       if (config_enabled(CONFIG_SMP))
+               return smp_num_siblings;
+
+       return 1;
 }
 
 /**
@@ -505,7 +509,7 @@ extern void mips_cm_unlock_other(void);
 
 #else /* !CONFIG_MIPS_CM */
 
-static inline void mips_cm_lock_other(unsigned int core) { }
+static inline void mips_cm_lock_other(unsigned int core, unsigned int vp) { }
 static inline void mips_cm_unlock_other(void) { }
 
 #endif /* !CONFIG_MIPS_CM */
index e09035239e5383117947fcabe8920cdf8d7608f1..8c519f9827a3036c3a16f3beb60ba182b71665fd 100644 (file)
@@ -106,6 +106,9 @@ BUILD_CPC_R_(revision,              MIPS_CPC_GCB_OFS + 0x20)
 BUILD_CPC_Cx_RW(cmd,           0x00)
 BUILD_CPC_Cx_RW(stat_conf,     0x08)
 BUILD_CPC_Cx_RW(other,         0x10)
+BUILD_CPC_Cx_RW(vp_stop,       0x20)
+BUILD_CPC_Cx_RW(vp_run,                0x28)
+BUILD_CPC_Cx_RW(vp_running,    0x30)
 
 /* CPC_Cx_CMD register fields */
 #define CPC_Cx_CMD_SHF                         0
index 3ad19ad04d8a282179423e9fcc5ecbb5557d26c7..25d01577d0b564943f282960b67751e5bf84636a 100644 (file)
 #define CP0_BADINSTR $8, 1
 #define CP0_COUNT $9
 #define CP0_ENTRYHI $10
+#define CP0_GUESTCTL1 $10, 4
+#define CP0_GUESTCTL2 $10, 5
+#define CP0_GUESTCTL3 $10, 6
 #define CP0_COMPARE $11
+#define CP0_GUESTCTL0EXT $11, 4
 #define CP0_STATUS $12
+#define CP0_GUESTCTL0 $12, 6
+#define CP0_GTOFFSET $12, 7
 #define CP0_CAUSE $13
 #define CP0_EPC $14
 #define CP0_PRID $15
 
 /* MIPS32/64 EntryHI bit definitions */
 #define MIPS_ENTRYHI_EHINV     (_ULCAST_(1) << 10)
+#define MIPS_ENTRYHI_ASIDX     (_ULCAST_(0x3) << 8)
+#define MIPS_ENTRYHI_ASID      (_ULCAST_(0xff) << 0)
 
 /*
  * R4x00 interrupt enable / cause bits
 #define         CAUSEF_IP7             (_ULCAST_(1)   << 15)
 #define CAUSEB_FDCI            21
 #define CAUSEF_FDCI            (_ULCAST_(1)   << 21)
+#define CAUSEB_WP              22
+#define CAUSEF_WP              (_ULCAST_(1)   << 22)
 #define CAUSEB_IV              23
 #define CAUSEF_IV              (_ULCAST_(1)   << 23)
 #define CAUSEB_PCI             26
 #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_KSCREXIST_SHIFT     (16)
+#define MIPS_CONF4_KSCREXIST   (_ULCAST_(255) << MIPS_CONF4_KSCREXIST_SHIFT)
 #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_CONF5_MRP         (_ULCAST_(1) << 3)
 #define MIPS_CONF5_LLB         (_ULCAST_(1) << 4)
 #define MIPS_CONF5_MVH         (_ULCAST_(1) << 5)
+#define MIPS_CONF5_VP          (_ULCAST_(1) << 7)
 #define MIPS_CONF5_FRE         (_ULCAST_(1) << 8)
 #define MIPS_CONF5_UFE         (_ULCAST_(1) << 9)
 #define MIPS_CONF5_MSAEN       (_ULCAST_(1) << 27)
 #define MIPS_CONF6_SYND                (_ULCAST_(1) << 13)
 /* proAptiv FTLB on/off bit */
 #define MIPS_CONF6_FTLBEN      (_ULCAST_(1) << 15)
+/* Loongson-3 FTLB on/off bit */
+#define MIPS_CONF6_FTLBDIS     (_ULCAST_(1) << 22)
 /* FTLB probability bits */
 #define MIPS_CONF6_FTLBP_SHIFT (16)
 
 /* FTLB probability bits for R6 */
 #define MIPS_CONF7_FTLBP_SHIFT (18)
 
+/* WatchLo* register definitions */
+#define MIPS_WATCHLO_IRW       (_ULCAST_(0x7) << 0)
+
+/* WatchHi* register definitions */
+#define MIPS_WATCHHI_M         (_ULCAST_(1) << 31)
+#define MIPS_WATCHHI_G         (_ULCAST_(1) << 30)
+#define MIPS_WATCHHI_WM                (_ULCAST_(0x3) << 28)
+#define MIPS_WATCHHI_WM_R_RVA  (_ULCAST_(0) << 28)
+#define MIPS_WATCHHI_WM_R_GPA  (_ULCAST_(1) << 28)
+#define MIPS_WATCHHI_WM_G_GVA  (_ULCAST_(2) << 28)
+#define MIPS_WATCHHI_EAS       (_ULCAST_(0x3) << 24)
+#define MIPS_WATCHHI_ASID      (_ULCAST_(0xff) << 16)
+#define MIPS_WATCHHI_MASK      (_ULCAST_(0x1ff) << 3)
+#define MIPS_WATCHHI_I         (_ULCAST_(1) << 2)
+#define MIPS_WATCHHI_R         (_ULCAST_(1) << 1)
+#define MIPS_WATCHHI_W         (_ULCAST_(1) << 0)
+#define MIPS_WATCHHI_IRW       (_ULCAST_(0x7) << 0)
+
 /* MAAR bit definitions */
 #define MIPS_MAAR_ADDR         ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
 #define MIPS_MAAR_ADDR_SHIFT   12
 #define MIPS_MAAR_S            (_ULCAST_(1) << 1)
 #define MIPS_MAAR_V            (_ULCAST_(1) << 0)
 
+/* EBase bit definitions */
+#define MIPS_EBASE_CPUNUM_SHIFT        0
+#define MIPS_EBASE_CPUNUM      (_ULCAST_(0x3ff) << 0)
+#define MIPS_EBASE_WG_SHIFT    11
+#define MIPS_EBASE_WG          (_ULCAST_(1) << 11)
+#define MIPS_EBASE_BASE_SHIFT  12
+#define MIPS_EBASE_BASE                (~_ULCAST_((1 << MIPS_EBASE_BASE_SHIFT) - 1))
+
 /* CMGCRBase bit definitions */
 #define MIPS_CMGCRB_BASE       11
 #define MIPS_CMGCRF_BASE       (~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1))
 #define MIPS_PWCTL_PSN_SHIFT   0
 #define MIPS_PWCTL_PSN_MASK    0x0000003f
 
+/* GuestCtl0 fields */
+#define MIPS_GCTL0_GM_SHIFT    31
+#define MIPS_GCTL0_GM          (_ULCAST_(1) << MIPS_GCTL0_GM_SHIFT)
+#define MIPS_GCTL0_RI_SHIFT    30
+#define MIPS_GCTL0_RI          (_ULCAST_(1) << MIPS_GCTL0_RI_SHIFT)
+#define MIPS_GCTL0_MC_SHIFT    29
+#define MIPS_GCTL0_MC          (_ULCAST_(1) << MIPS_GCTL0_MC_SHIFT)
+#define MIPS_GCTL0_CP0_SHIFT   28
+#define MIPS_GCTL0_CP0         (_ULCAST_(1) << MIPS_GCTL0_CP0_SHIFT)
+#define MIPS_GCTL0_AT_SHIFT    26
+#define MIPS_GCTL0_AT          (_ULCAST_(0x3) << MIPS_GCTL0_AT_SHIFT)
+#define MIPS_GCTL0_GT_SHIFT    25
+#define MIPS_GCTL0_GT          (_ULCAST_(1) << MIPS_GCTL0_GT_SHIFT)
+#define MIPS_GCTL0_CG_SHIFT    24
+#define MIPS_GCTL0_CG          (_ULCAST_(1) << MIPS_GCTL0_CG_SHIFT)
+#define MIPS_GCTL0_CF_SHIFT    23
+#define MIPS_GCTL0_CF          (_ULCAST_(1) << MIPS_GCTL0_CF_SHIFT)
+#define MIPS_GCTL0_G1_SHIFT    22
+#define MIPS_GCTL0_G1          (_ULCAST_(1) << MIPS_GCTL0_G1_SHIFT)
+#define MIPS_GCTL0_G0E_SHIFT   19
+#define MIPS_GCTL0_G0E         (_ULCAST_(1) << MIPS_GCTL0_G0E_SHIFT)
+#define MIPS_GCTL0_PT_SHIFT    18
+#define MIPS_GCTL0_PT          (_ULCAST_(1) << MIPS_GCTL0_PT_SHIFT)
+#define MIPS_GCTL0_RAD_SHIFT   9
+#define MIPS_GCTL0_RAD         (_ULCAST_(1) << MIPS_GCTL0_RAD_SHIFT)
+#define MIPS_GCTL0_DRG_SHIFT   8
+#define MIPS_GCTL0_DRG         (_ULCAST_(1) << MIPS_GCTL0_DRG_SHIFT)
+#define MIPS_GCTL0_G2_SHIFT    7
+#define MIPS_GCTL0_G2          (_ULCAST_(1) << MIPS_GCTL0_G2_SHIFT)
+#define MIPS_GCTL0_GEXC_SHIFT  2
+#define MIPS_GCTL0_GEXC                (_ULCAST_(0x1f) << MIPS_GCTL0_GEXC_SHIFT)
+#define MIPS_GCTL0_SFC2_SHIFT  1
+#define MIPS_GCTL0_SFC2                (_ULCAST_(1) << MIPS_GCTL0_SFC2_SHIFT)
+#define MIPS_GCTL0_SFC1_SHIFT  0
+#define MIPS_GCTL0_SFC1                (_ULCAST_(1) << MIPS_GCTL0_SFC1_SHIFT)
+
+/* GuestCtl0.AT Guest address translation control */
+#define MIPS_GCTL0_AT_ROOT     1  /* Guest MMU under Root control */
+#define MIPS_GCTL0_AT_GUEST    3  /* Guest MMU under Guest control */
+
+/* GuestCtl0.GExcCode Hypervisor exception cause codes */
+#define MIPS_GCTL0_GEXC_GPSI   0  /* Guest Privileged Sensitive Instruction */
+#define MIPS_GCTL0_GEXC_GSFC   1  /* Guest Software Field Change */
+#define MIPS_GCTL0_GEXC_HC     2  /* Hypercall */
+#define MIPS_GCTL0_GEXC_GRR    3  /* Guest Reserved Instruction Redirect */
+#define MIPS_GCTL0_GEXC_GVA    8  /* Guest Virtual Address available */
+#define MIPS_GCTL0_GEXC_GHFC   9  /* Guest Hardware Field Change */
+#define MIPS_GCTL0_GEXC_GPA    10 /* Guest Physical Address available */
+
+/* GuestCtl0Ext fields */
+#define MIPS_GCTL0EXT_RPW_SHIFT        8
+#define MIPS_GCTL0EXT_RPW      (_ULCAST_(0x3) << MIPS_GCTL0EXT_RPW_SHIFT)
+#define MIPS_GCTL0EXT_NCC_SHIFT        6
+#define MIPS_GCTL0EXT_NCC      (_ULCAST_(0x3) << MIPS_GCTL0EXT_NCC_SHIFT)
+#define MIPS_GCTL0EXT_CGI_SHIFT        4
+#define MIPS_GCTL0EXT_CGI      (_ULCAST_(1) << MIPS_GCTL0EXT_CGI_SHIFT)
+#define MIPS_GCTL0EXT_FCD_SHIFT        3
+#define MIPS_GCTL0EXT_FCD      (_ULCAST_(1) << MIPS_GCTL0EXT_FCD_SHIFT)
+#define MIPS_GCTL0EXT_OG_SHIFT 2
+#define MIPS_GCTL0EXT_OG       (_ULCAST_(1) << MIPS_GCTL0EXT_OG_SHIFT)
+#define MIPS_GCTL0EXT_BG_SHIFT 1
+#define MIPS_GCTL0EXT_BG       (_ULCAST_(1) << MIPS_GCTL0EXT_BG_SHIFT)
+#define MIPS_GCTL0EXT_MG_SHIFT 0
+#define MIPS_GCTL0EXT_MG       (_ULCAST_(1) << MIPS_GCTL0EXT_MG_SHIFT)
+
+/* GuestCtl0Ext.RPW Root page walk configuration */
+#define MIPS_GCTL0EXT_RPW_BOTH 0  /* Root PW for GPA->RPA and RVA->RPA */
+#define MIPS_GCTL0EXT_RPW_GPA  2  /* Root PW for GPA->RPA */
+#define MIPS_GCTL0EXT_RPW_RVA  3  /* Root PW for RVA->RPA */
+
+/* GuestCtl0Ext.NCC Nested cache coherency attributes */
+#define MIPS_GCTL0EXT_NCC_IND  0  /* Guest CCA independent of Root CCA */
+#define MIPS_GCTL0EXT_NCC_MOD  1  /* Guest CCA modified by Root CCA */
+
+/* GuestCtl1 fields */
+#define MIPS_GCTL1_ID_SHIFT    0
+#define MIPS_GCTL1_ID_WIDTH    8
+#define MIPS_GCTL1_ID          (_ULCAST_(0xff) << MIPS_GCTL1_ID_SHIFT)
+#define MIPS_GCTL1_RID_SHIFT   16
+#define MIPS_GCTL1_RID_WIDTH   8
+#define MIPS_GCTL1_RID         (_ULCAST_(0xff) << MIPS_GCTL1_RID_SHIFT)
+#define MIPS_GCTL1_EID_SHIFT   24
+#define MIPS_GCTL1_EID_WIDTH   8
+#define MIPS_GCTL1_EID         (_ULCAST_(0xff) << MIPS_GCTL1_EID_SHIFT)
+
+/* GuestID reserved for root context */
+#define MIPS_GCTL1_ROOT_GUESTID        0
+
 /* CDMMBase register bit definitions */
 #define MIPS_CDMMBASE_SIZE_SHIFT 0
 #define MIPS_CDMMBASE_SIZE     (_ULCAST_(511) << MIPS_CDMMBASE_SIZE_SHIFT)
 /* Disable Branch Return Cache */
 #define R10K_DIAG_D_BRC                (_ULCAST_(1) << 22)
 
+/* Flush ITLB */
+#define LOONGSON_DIAG_ITLB     (_ULCAST_(1) << 2)
+/* Flush DTLB */
+#define LOONGSON_DIAG_DTLB     (_ULCAST_(1) << 3)
+/* Flush VTLB */
+#define LOONGSON_DIAG_VTLB     (_ULCAST_(1) << 12)
+/* Flush FTLB */
+#define LOONGSON_DIAG_FTLB     (_ULCAST_(1) << 13)
+
 /*
  * Coprocessor 1 (FPU) register names
  */
@@ -1186,9 +1323,15 @@ do {                                                                     \
 #define read_c0_context()      __read_ulong_c0_register($4, 0)
 #define write_c0_context(val)  __write_ulong_c0_register($4, 0, val)
 
+#define read_c0_contextconfig()                __read_32bit_c0_register($4, 1)
+#define write_c0_contextconfig(val)    __write_32bit_c0_register($4, 1, val)
+
 #define read_c0_userlocal()    __read_ulong_c0_register($4, 2)
 #define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val)
 
+#define read_c0_xcontextconfig()       __read_ulong_c0_register($4, 3)
+#define write_c0_xcontextconfig(val)   __write_ulong_c0_register($4, 3, val)
+
 #define read_c0_pagemask()     __read_32bit_c0_register($5, 0)
 #define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val)
 
@@ -1206,6 +1349,9 @@ do {                                                                      \
 #define read_c0_badvaddr()     __read_ulong_c0_register($8, 0)
 #define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val)
 
+#define read_c0_badinstr()     __read_32bit_c0_register($8, 1)
+#define read_c0_badinstrp()    __read_32bit_c0_register($8, 2)
+
 #define read_c0_count()                __read_32bit_c0_register($9, 0)
 #define write_c0_count(val)    __write_32bit_c0_register($9, 0, val)
 
@@ -1218,9 +1364,21 @@ do {                                                                     \
 #define read_c0_entryhi()      __read_ulong_c0_register($10, 0)
 #define write_c0_entryhi(val)  __write_ulong_c0_register($10, 0, val)
 
+#define read_c0_guestctl1()    __read_32bit_c0_register($10, 4)
+#define write_c0_guestctl1(val)        __write_32bit_c0_register($10, 4, val)
+
+#define read_c0_guestctl2()    __read_32bit_c0_register($10, 5)
+#define write_c0_guestctl2(val)        __write_32bit_c0_register($10, 5, val)
+
+#define read_c0_guestctl3()    __read_32bit_c0_register($10, 6)
+#define write_c0_guestctl3(val)        __write_32bit_c0_register($10, 6, val)
+
 #define read_c0_compare()      __read_32bit_c0_register($11, 0)
 #define write_c0_compare(val)  __write_32bit_c0_register($11, 0, val)
 
+#define read_c0_guestctl0ext() __read_32bit_c0_register($11, 4)
+#define write_c0_guestctl0ext(val) __write_32bit_c0_register($11, 4, val)
+
 #define read_c0_compare2()     __read_32bit_c0_register($11, 6) /* pnx8550 */
 #define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val)
 
@@ -1231,6 +1389,12 @@ do {                                                                     \
 
 #define write_c0_status(val)   __write_32bit_c0_register($12, 0, val)
 
+#define read_c0_guestctl0()    __read_32bit_c0_register($12, 6)
+#define write_c0_guestctl0(val)        __write_32bit_c0_register($12, 6, val)
+
+#define read_c0_gtoffset()     __read_32bit_c0_register($12, 7)
+#define write_c0_gtoffset(val) __write_32bit_c0_register($12, 7, val)
+
 #define read_c0_cause()                __read_32bit_c0_register($13, 0)
 #define write_c0_cause(val)    __write_32bit_c0_register($13, 0, val)
 
@@ -1416,6 +1580,9 @@ do {                                                                      \
 #define read_c0_ebase()                __read_32bit_c0_register($15, 1)
 #define write_c0_ebase(val)    __write_32bit_c0_register($15, 1, val)
 
+#define read_c0_ebase_64()     __read_64bit_c0_register($15, 1)
+#define write_c0_ebase_64(val) __write_64bit_c0_register($15, 1, val)
+
 #define read_c0_cdmmbase()     __read_ulong_c0_register($15, 2)
 #define write_c0_cdmmbase(val) __write_ulong_c0_register($15, 2, val)
 
@@ -1442,6 +1609,12 @@ do {                                                                     \
 #define read_c0_pwctl()                __read_32bit_c0_register($6, 6)
 #define write_c0_pwctl(val)    __write_32bit_c0_register($6, 6, val)
 
+#define read_c0_pgd()          __read_64bit_c0_register($9, 7)
+#define write_c0_pgd(val)      __write_64bit_c0_register($9, 7, val)
+
+#define read_c0_kpgd()         __read_64bit_c0_register($31, 7)
+#define write_c0_kpgd(val)     __write_64bit_c0_register($31, 7, val)
+
 /* Cavium OCTEON (cnMIPS) */
 #define read_c0_cvmcount()     __read_ulong_c0_register($9, 6)
 #define write_c0_cvmcount(val) __write_ulong_c0_register($9, 6, val)
@@ -1506,6 +1679,317 @@ do {                                                                    \
 #define read_c0_brcm_sleepcount()      __read_32bit_c0_register($22, 7)
 #define write_c0_brcm_sleepcount(val)  __write_32bit_c0_register($22, 7, val)
 
+/*
+ * Macros to access the guest system control coprocessor
+ */
+
+#ifdef TOOLCHAIN_SUPPORTS_VIRT
+
+#define __read_32bit_gc0_register(source, sel)                         \
+({ int __res;                                                          \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tmips32r2\n\t"                                    \
+               ".set\tvirt\n\t"                                        \
+               "mfgc0\t%0, $%1, %2\n\t"                                \
+               ".set\tpop"                                             \
+               : "=r" (__res)                                          \
+               : "i" (source), "i" (sel));                             \
+       __res;                                                          \
+})
+
+#define __read_64bit_gc0_register(source, sel)                         \
+({ unsigned long long __res;                                           \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tmips64r2\n\t"                                    \
+               ".set\tvirt\n\t"                                        \
+               "dmfgc0\t%0, $%1, %2\n\t"                       \
+               ".set\tpop"                                             \
+               : "=r" (__res)                                          \
+               : "i" (source), "i" (sel));                             \
+       __res;                                                          \
+})
+
+#define __write_32bit_gc0_register(register, sel, value)               \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tmips32r2\n\t"                                    \
+               ".set\tvirt\n\t"                                        \
+               "mtgc0\t%z0, $%1, %2\n\t"                               \
+               ".set\tpop"                                             \
+               : : "Jr" ((unsigned int)(value)),                       \
+                   "i" (register), "i" (sel));                         \
+} while (0)
+
+#define __write_64bit_gc0_register(register, sel, value)               \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tmips64r2\n\t"                                    \
+               ".set\tvirt\n\t"                                        \
+               "dmtgc0\t%z0, $%1, %2\n\t"                              \
+               ".set\tpop"                                             \
+               : : "Jr" (value),                                       \
+                   "i" (register), "i" (sel));                         \
+} while (0)
+
+#else  /* TOOLCHAIN_SUPPORTS_VIRT */
+
+#define __read_32bit_gc0_register(source, sel)                         \
+({ int __res;                                                          \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tnoat\n\t"                                        \
+               "# mfgc0\t$1, $%1, %2\n\t"                              \
+               ".word\t(0x40610000 | %1 << 11 | %2)\n\t"               \
+               "move\t%0, $1\n\t"                                      \
+               ".set\tpop"                                             \
+               : "=r" (__res)                                          \
+               : "i" (source), "i" (sel));                             \
+       __res;                                                          \
+})
+
+#define __read_64bit_gc0_register(source, sel)                         \
+({ unsigned long long __res;                                           \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tnoat\n\t"                                        \
+               "# dmfgc0\t$1, $%1, %2\n\t"                             \
+               ".word\t(0x40610100 | %1 << 11 | %2)\n\t"               \
+               "move\t%0, $1\n\t"                                      \
+               ".set\tpop"                                             \
+               : "=r" (__res)                                          \
+               : "i" (source), "i" (sel));                             \
+       __res;                                                          \
+})
+
+#define __write_32bit_gc0_register(register, sel, value)               \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tnoat\n\t"                                        \
+               "move\t$1, %0\n\t"                                      \
+               "# mtgc0\t$1, $%1, %2\n\t"                              \
+               ".word\t(0x40610200 | %1 << 11 | %2)\n\t"               \
+               ".set\tpop"                                             \
+               : : "Jr" ((unsigned int)(value)),                       \
+                   "i" (register), "i" (sel));                         \
+} while (0)
+
+#define __write_64bit_gc0_register(register, sel, value)               \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+               ".set\tpush\n\t"                                        \
+               ".set\tnoat\n\t"                                        \
+               "move\t$1, %0\n\t"                                      \
+               "# dmtgc0\t$1, $%1, %2\n\t"                             \
+               ".word\t(0x40610300 | %1 << 11 | %2)\n\t"               \
+               ".set\tpop"                                             \
+               : : "Jr" (value),                                       \
+                   "i" (register), "i" (sel));                         \
+} while (0)
+
+#endif /* !TOOLCHAIN_SUPPORTS_VIRT */
+
+#define __read_ulong_gc0_register(reg, sel)                            \
+       ((sizeof(unsigned long) == 4) ?                                 \
+       (unsigned long) __read_32bit_gc0_register(reg, sel) :           \
+       (unsigned long) __read_64bit_gc0_register(reg, sel))
+
+#define __write_ulong_gc0_register(reg, sel, val)                      \
+do {                                                                   \
+       if (sizeof(unsigned long) == 4)                                 \
+               __write_32bit_gc0_register(reg, sel, val);              \
+       else                                                            \
+               __write_64bit_gc0_register(reg, sel, val);              \
+} while (0)
+
+#define read_gc0_index()               __read_32bit_gc0_register(0, 0)
+#define write_gc0_index(val)           __write_32bit_gc0_register(0, 0, val)
+
+#define read_gc0_entrylo0()            __read_ulong_gc0_register(2, 0)
+#define write_gc0_entrylo0(val)                __write_ulong_gc0_register(2, 0, val)
+
+#define read_gc0_entrylo1()            __read_ulong_gc0_register(3, 0)
+#define write_gc0_entrylo1(val)                __write_ulong_gc0_register(3, 0, val)
+
+#define read_gc0_context()             __read_ulong_gc0_register(4, 0)
+#define write_gc0_context(val)         __write_ulong_gc0_register(4, 0, val)
+
+#define read_gc0_contextconfig()       __read_32bit_gc0_register(4, 1)
+#define write_gc0_contextconfig(val)   __write_32bit_gc0_register(4, 1, val)
+
+#define read_gc0_userlocal()           __read_ulong_gc0_register(4, 2)
+#define write_gc0_userlocal(val)       __write_ulong_gc0_register(4, 2, val)
+
+#define read_gc0_xcontextconfig()      __read_ulong_gc0_register(4, 3)
+#define write_gc0_xcontextconfig(val)  __write_ulong_gc0_register(4, 3, val)
+
+#define read_gc0_pagemask()            __read_32bit_gc0_register(5, 0)
+#define write_gc0_pagemask(val)                __write_32bit_gc0_register(5, 0, val)
+
+#define read_gc0_pagegrain()           __read_32bit_gc0_register(5, 1)
+#define write_gc0_pagegrain(val)       __write_32bit_gc0_register(5, 1, val)
+
+#define read_gc0_segctl0()             __read_ulong_gc0_register(5, 2)
+#define write_gc0_segctl0(val)         __write_ulong_gc0_register(5, 2, val)
+
+#define read_gc0_segctl1()             __read_ulong_gc0_register(5, 3)
+#define write_gc0_segctl1(val)         __write_ulong_gc0_register(5, 3, val)
+
+#define read_gc0_segctl2()             __read_ulong_gc0_register(5, 4)
+#define write_gc0_segctl2(val)         __write_ulong_gc0_register(5, 4, val)
+
+#define read_gc0_pwbase()              __read_ulong_gc0_register(5, 5)
+#define write_gc0_pwbase(val)          __write_ulong_gc0_register(5, 5, val)
+
+#define read_gc0_pwfield()             __read_ulong_gc0_register(5, 6)
+#define write_gc0_pwfield(val)         __write_ulong_gc0_register(5, 6, val)
+
+#define read_gc0_pwsize()              __read_ulong_gc0_register(5, 7)
+#define write_gc0_pwsize(val)          __write_ulong_gc0_register(5, 7, val)
+
+#define read_gc0_wired()               __read_32bit_gc0_register(6, 0)
+#define write_gc0_wired(val)           __write_32bit_gc0_register(6, 0, val)
+
+#define read_gc0_pwctl()               __read_32bit_gc0_register(6, 6)
+#define write_gc0_pwctl(val)           __write_32bit_gc0_register(6, 6, val)
+
+#define read_gc0_hwrena()              __read_32bit_gc0_register(7, 0)
+#define write_gc0_hwrena(val)          __write_32bit_gc0_register(7, 0, val)
+
+#define read_gc0_badvaddr()            __read_ulong_gc0_register(8, 0)
+#define write_gc0_badvaddr(val)                __write_ulong_gc0_register(8, 0, val)
+
+#define read_gc0_badinstr()            __read_32bit_gc0_register(8, 1)
+#define write_gc0_badinstr(val)                __write_32bit_gc0_register(8, 1, val)
+
+#define read_gc0_badinstrp()           __read_32bit_gc0_register(8, 2)
+#define write_gc0_badinstrp(val)       __write_32bit_gc0_register(8, 2, val)
+
+#define read_gc0_count()               __read_32bit_gc0_register(9, 0)
+
+#define read_gc0_entryhi()             __read_ulong_gc0_register(10, 0)
+#define write_gc0_entryhi(val)         __write_ulong_gc0_register(10, 0, val)
+
+#define read_gc0_compare()             __read_32bit_gc0_register(11, 0)
+#define write_gc0_compare(val)         __write_32bit_gc0_register(11, 0, val)
+
+#define read_gc0_status()              __read_32bit_gc0_register(12, 0)
+#define write_gc0_status(val)          __write_32bit_gc0_register(12, 0, val)
+
+#define read_gc0_intctl()              __read_32bit_gc0_register(12, 1)
+#define write_gc0_intctl(val)          __write_32bit_gc0_register(12, 1, val)
+
+#define read_gc0_cause()               __read_32bit_gc0_register(13, 0)
+#define write_gc0_cause(val)           __write_32bit_gc0_register(13, 0, val)
+
+#define read_gc0_epc()                 __read_ulong_gc0_register(14, 0)
+#define write_gc0_epc(val)             __write_ulong_gc0_register(14, 0, val)
+
+#define read_gc0_ebase()               __read_32bit_gc0_register(15, 1)
+#define write_gc0_ebase(val)           __write_32bit_gc0_register(15, 1, val)
+
+#define read_gc0_ebase_64()            __read_64bit_gc0_register(15, 1)
+#define write_gc0_ebase_64(val)                __write_64bit_gc0_register(15, 1, val)
+
+#define read_gc0_config()              __read_32bit_gc0_register(16, 0)
+#define read_gc0_config1()             __read_32bit_gc0_register(16, 1)
+#define read_gc0_config2()             __read_32bit_gc0_register(16, 2)
+#define read_gc0_config3()             __read_32bit_gc0_register(16, 3)
+#define read_gc0_config4()             __read_32bit_gc0_register(16, 4)
+#define read_gc0_config5()             __read_32bit_gc0_register(16, 5)
+#define read_gc0_config6()             __read_32bit_gc0_register(16, 6)
+#define read_gc0_config7()             __read_32bit_gc0_register(16, 7)
+#define write_gc0_config(val)          __write_32bit_gc0_register(16, 0, val)
+#define write_gc0_config1(val)         __write_32bit_gc0_register(16, 1, val)
+#define write_gc0_config2(val)         __write_32bit_gc0_register(16, 2, val)
+#define write_gc0_config3(val)         __write_32bit_gc0_register(16, 3, val)
+#define write_gc0_config4(val)         __write_32bit_gc0_register(16, 4, val)
+#define write_gc0_config5(val)         __write_32bit_gc0_register(16, 5, val)
+#define write_gc0_config6(val)         __write_32bit_gc0_register(16, 6, val)
+#define write_gc0_config7(val)         __write_32bit_gc0_register(16, 7, val)
+
+#define read_gc0_watchlo0()            __read_ulong_gc0_register(18, 0)
+#define read_gc0_watchlo1()            __read_ulong_gc0_register(18, 1)
+#define read_gc0_watchlo2()            __read_ulong_gc0_register(18, 2)
+#define read_gc0_watchlo3()            __read_ulong_gc0_register(18, 3)
+#define read_gc0_watchlo4()            __read_ulong_gc0_register(18, 4)
+#define read_gc0_watchlo5()            __read_ulong_gc0_register(18, 5)
+#define read_gc0_watchlo6()            __read_ulong_gc0_register(18, 6)
+#define read_gc0_watchlo7()            __read_ulong_gc0_register(18, 7)
+#define write_gc0_watchlo0(val)                __write_ulong_gc0_register(18, 0, val)
+#define write_gc0_watchlo1(val)                __write_ulong_gc0_register(18, 1, val)
+#define write_gc0_watchlo2(val)                __write_ulong_gc0_register(18, 2, val)
+#define write_gc0_watchlo3(val)                __write_ulong_gc0_register(18, 3, val)
+#define write_gc0_watchlo4(val)                __write_ulong_gc0_register(18, 4, val)
+#define write_gc0_watchlo5(val)                __write_ulong_gc0_register(18, 5, val)
+#define write_gc0_watchlo6(val)                __write_ulong_gc0_register(18, 6, val)
+#define write_gc0_watchlo7(val)                __write_ulong_gc0_register(18, 7, val)
+
+#define read_gc0_watchhi0()            __read_32bit_gc0_register(19, 0)
+#define read_gc0_watchhi1()            __read_32bit_gc0_register(19, 1)
+#define read_gc0_watchhi2()            __read_32bit_gc0_register(19, 2)
+#define read_gc0_watchhi3()            __read_32bit_gc0_register(19, 3)
+#define read_gc0_watchhi4()            __read_32bit_gc0_register(19, 4)
+#define read_gc0_watchhi5()            __read_32bit_gc0_register(19, 5)
+#define read_gc0_watchhi6()            __read_32bit_gc0_register(19, 6)
+#define read_gc0_watchhi7()            __read_32bit_gc0_register(19, 7)
+#define write_gc0_watchhi0(val)                __write_32bit_gc0_register(19, 0, val)
+#define write_gc0_watchhi1(val)                __write_32bit_gc0_register(19, 1, val)
+#define write_gc0_watchhi2(val)                __write_32bit_gc0_register(19, 2, val)
+#define write_gc0_watchhi3(val)                __write_32bit_gc0_register(19, 3, val)
+#define write_gc0_watchhi4(val)                __write_32bit_gc0_register(19, 4, val)
+#define write_gc0_watchhi5(val)                __write_32bit_gc0_register(19, 5, val)
+#define write_gc0_watchhi6(val)                __write_32bit_gc0_register(19, 6, val)
+#define write_gc0_watchhi7(val)                __write_32bit_gc0_register(19, 7, val)
+
+#define read_gc0_xcontext()            __read_ulong_gc0_register(20, 0)
+#define write_gc0_xcontext(val)                __write_ulong_gc0_register(20, 0, val)
+
+#define read_gc0_perfctrl0()           __read_32bit_gc0_register(25, 0)
+#define write_gc0_perfctrl0(val)       __write_32bit_gc0_register(25, 0, val)
+#define read_gc0_perfcntr0()           __read_32bit_gc0_register(25, 1)
+#define write_gc0_perfcntr0(val)       __write_32bit_gc0_register(25, 1, val)
+#define read_gc0_perfcntr0_64()                __read_64bit_gc0_register(25, 1)
+#define write_gc0_perfcntr0_64(val)    __write_64bit_gc0_register(25, 1, val)
+#define read_gc0_perfctrl1()           __read_32bit_gc0_register(25, 2)
+#define write_gc0_perfctrl1(val)       __write_32bit_gc0_register(25, 2, val)
+#define read_gc0_perfcntr1()           __read_32bit_gc0_register(25, 3)
+#define write_gc0_perfcntr1(val)       __write_32bit_gc0_register(25, 3, val)
+#define read_gc0_perfcntr1_64()                __read_64bit_gc0_register(25, 3)
+#define write_gc0_perfcntr1_64(val)    __write_64bit_gc0_register(25, 3, val)
+#define read_gc0_perfctrl2()           __read_32bit_gc0_register(25, 4)
+#define write_gc0_perfctrl2(val)       __write_32bit_gc0_register(25, 4, val)
+#define read_gc0_perfcntr2()           __read_32bit_gc0_register(25, 5)
+#define write_gc0_perfcntr2(val)       __write_32bit_gc0_register(25, 5, val)
+#define read_gc0_perfcntr2_64()                __read_64bit_gc0_register(25, 5)
+#define write_gc0_perfcntr2_64(val)    __write_64bit_gc0_register(25, 5, val)
+#define read_gc0_perfctrl3()           __read_32bit_gc0_register(25, 6)
+#define write_gc0_perfctrl3(val)       __write_32bit_gc0_register(25, 6, val)
+#define read_gc0_perfcntr3()           __read_32bit_gc0_register(25, 7)
+#define write_gc0_perfcntr3(val)       __write_32bit_gc0_register(25, 7, val)
+#define read_gc0_perfcntr3_64()                __read_64bit_gc0_register(25, 7)
+#define write_gc0_perfcntr3_64(val)    __write_64bit_gc0_register(25, 7, val)
+
+#define read_gc0_errorepc()            __read_ulong_gc0_register(30, 0)
+#define write_gc0_errorepc(val)                __write_ulong_gc0_register(30, 0, val)
+
+#define read_gc0_kscratch1()           __read_ulong_gc0_register(31, 2)
+#define read_gc0_kscratch2()           __read_ulong_gc0_register(31, 3)
+#define read_gc0_kscratch3()           __read_ulong_gc0_register(31, 4)
+#define read_gc0_kscratch4()           __read_ulong_gc0_register(31, 5)
+#define read_gc0_kscratch5()           __read_ulong_gc0_register(31, 6)
+#define read_gc0_kscratch6()           __read_ulong_gc0_register(31, 7)
+#define write_gc0_kscratch1(val)       __write_ulong_gc0_register(31, 2, val)
+#define write_gc0_kscratch2(val)       __write_ulong_gc0_register(31, 3, val)
+#define write_gc0_kscratch3(val)       __write_ulong_gc0_register(31, 4, val)
+#define write_gc0_kscratch4(val)       __write_ulong_gc0_register(31, 5, val)
+#define write_gc0_kscratch5(val)       __write_ulong_gc0_register(31, 6, val)
+#define write_gc0_kscratch6(val)       __write_ulong_gc0_register(31, 7, val)
+
 /*
  * Macros to access the floating point coprocessor control registers
  */
@@ -2001,47 +2485,159 @@ static inline void tlb_write_random(void)
                ".set reorder");
 }
 
+#ifdef TOOLCHAIN_SUPPORTS_VIRT
+
 /*
- * Manipulate bits in a c0 register.
+ * Guest TLB operations.
+ *
+ * It is responsibility of the caller to take care of any TLB hazards.
  */
-#define __BUILD_SET_C0(name)                                   \
+static inline void guest_tlb_probe(void)
+{
+       __asm__ __volatile__(
+               ".set push\n\t"
+               ".set noreorder\n\t"
+               ".set virt\n\t"
+               "tlbgp\n\t"
+               ".set pop");
+}
+
+static inline void guest_tlb_read(void)
+{
+       __asm__ __volatile__(
+               ".set push\n\t"
+               ".set noreorder\n\t"
+               ".set virt\n\t"
+               "tlbgr\n\t"
+               ".set pop");
+}
+
+static inline void guest_tlb_write_indexed(void)
+{
+       __asm__ __volatile__(
+               ".set push\n\t"
+               ".set noreorder\n\t"
+               ".set virt\n\t"
+               "tlbgwi\n\t"
+               ".set pop");
+}
+
+static inline void guest_tlb_write_random(void)
+{
+       __asm__ __volatile__(
+               ".set push\n\t"
+               ".set noreorder\n\t"
+               ".set virt\n\t"
+               "tlbgwr\n\t"
+               ".set pop");
+}
+
+/*
+ * Guest TLB Invalidate Flush
+ */
+static inline void guest_tlbinvf(void)
+{
+       __asm__ __volatile__(
+               ".set push\n\t"
+               ".set noreorder\n\t"
+               ".set virt\n\t"
+               "tlbginvf\n\t"
+               ".set pop");
+}
+
+#else  /* TOOLCHAIN_SUPPORTS_VIRT */
+
+/*
+ * Guest TLB operations.
+ *
+ * It is responsibility of the caller to take care of any TLB hazards.
+ */
+static inline void guest_tlb_probe(void)
+{
+       __asm__ __volatile__(
+               "# tlbgp\n\t"
+               ".word 0x42000010");
+}
+
+static inline void guest_tlb_read(void)
+{
+       __asm__ __volatile__(
+               "# tlbgr\n\t"
+               ".word 0x42000009");
+}
+
+static inline void guest_tlb_write_indexed(void)
+{
+       __asm__ __volatile__(
+               "# tlbgwi\n\t"
+               ".word 0x4200000a");
+}
+
+static inline void guest_tlb_write_random(void)
+{
+       __asm__ __volatile__(
+               "# tlbgwr\n\t"
+               ".word 0x4200000e");
+}
+
+/*
+ * Guest TLB Invalidate Flush
+ */
+static inline void guest_tlbinvf(void)
+{
+       __asm__ __volatile__(
+               "# tlbginvf\n\t"
+               ".word 0x4200000c");
+}
+
+#endif /* !TOOLCHAIN_SUPPORTS_VIRT */
+
+/*
+ * Manipulate bits in a register.
+ */
+#define __BUILD_SET_COMMON(name)                               \
 static inline unsigned int                                     \
-set_c0_##name(unsigned int set)                                        \
+set_##name(unsigned int set)                                   \
 {                                                              \
        unsigned int res, new;                                  \
                                                                \
-       res = read_c0_##name();                                 \
+       res = read_##name();                                    \
        new = res | set;                                        \
-       write_c0_##name(new);                                   \
+       write_##name(new);                                      \
                                                                \
        return res;                                             \
 }                                                              \
                                                                \
 static inline unsigned int                                     \
-clear_c0_##name(unsigned int clear)                            \
+clear_##name(unsigned int clear)                               \
 {                                                              \
        unsigned int res, new;                                  \
                                                                \
-       res = read_c0_##name();                                 \
+       res = read_##name();                                    \
        new = res & ~clear;                                     \
-       write_c0_##name(new);                                   \
+       write_##name(new);                                      \
                                                                \
        return res;                                             \
 }                                                              \
                                                                \
 static inline unsigned int                                     \
-change_c0_##name(unsigned int change, unsigned int val)                \
+change_##name(unsigned int change, unsigned int val)           \
 {                                                              \
        unsigned int res, new;                                  \
                                                                \
-       res = read_c0_##name();                                 \
+       res = read_##name();                                    \
        new = res & ~change;                                    \
        new |= (val & change);                                  \
-       write_c0_##name(new);                                   \
+       write_##name(new);                                      \
                                                                \
        return res;                                             \
 }
 
+/*
+ * Manipulate bits in a c0 register.
+ */
+#define __BUILD_SET_C0(name)   __BUILD_SET_COMMON(c0_##name)
+
 __BUILD_SET_C0(status)
 __BUILD_SET_C0(cause)
 __BUILD_SET_C0(config)
@@ -2050,6 +2646,11 @@ __BUILD_SET_C0(intcontrol)
 __BUILD_SET_C0(intctl)
 __BUILD_SET_C0(srsmap)
 __BUILD_SET_C0(pagegrain)
+__BUILD_SET_C0(guestctl0)
+__BUILD_SET_C0(guestctl0ext)
+__BUILD_SET_C0(guestctl1)
+__BUILD_SET_C0(guestctl2)
+__BUILD_SET_C0(guestctl3)
 __BUILD_SET_C0(brcm_config_0)
 __BUILD_SET_C0(brcm_bus_pll)
 __BUILD_SET_C0(brcm_reset)
@@ -2058,13 +2659,22 @@ __BUILD_SET_C0(brcm_cmt_ctrl)
 __BUILD_SET_C0(brcm_config)
 __BUILD_SET_C0(brcm_mode)
 
+/*
+ * Manipulate bits in a guest c0 register.
+ */
+#define __BUILD_SET_GC0(name)  __BUILD_SET_COMMON(gc0_##name)
+
+__BUILD_SET_GC0(status)
+__BUILD_SET_GC0(cause)
+__BUILD_SET_GC0(ebase)
+
 /*
  * 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;
+       return read_c0_ebase() & MIPS_EBASE_CPUNUM;
 }
 
 #endif /* !__ASSEMBLY__ */
index 45914b59824c11a14a9ec76e6fe016dccc3eaaaf..fc57e135cb0a9b831062bfb93a2b184908e3e9d7 100644 (file)
@@ -65,37 +65,32 @@ extern unsigned long pgd_current[];
        back_to_back_c0_hazard();                                       \
        TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
-#define ASID_INC       0x40
-#define ASID_MASK      0xfc0
-
-#elif defined(CONFIG_CPU_R8000)
-
-#define ASID_INC       0x10
-#define ASID_MASK      0xff0
-
-#else /* FIXME: not correct for R6000 */
+/*
+ *  All unused by hardware upper bits will be considered
+ *  as a software asid extension.
+ */
+static unsigned long asid_version_mask(unsigned int cpu)
+{
+       unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]);
 
-#define ASID_INC       0x1
-#define ASID_MASK      0xff
+       return ~(asid_mask | (asid_mask - 1));
+}
 
-#endif
+static unsigned long asid_first_version(unsigned int cpu)
+{
+       return ~asid_version_mask(cpu) + 1;
+}
 
 #define cpu_context(cpu, mm)   ((mm)->context.asid[cpu])
-#define cpu_asid(cpu, mm)      (cpu_context((cpu), (mm)) & ASID_MASK)
 #define asid_cache(cpu)                (cpu_data[cpu].asid_cache)
+#define cpu_asid(cpu, mm) \
+       (cpu_context((cpu), (mm)) & cpu_asid_mask(&cpu_data[cpu]))
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
-/*
- *  All unused by hardware upper bits will be considered
- *  as a software asid extension.
- */
-#define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
-#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
 
 /* Normal, classic MIPS get_new_mmu_context */
 static inline void
@@ -104,7 +99,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
        extern void kvm_local_flush_tlb_all(void);
        unsigned long asid = asid_cache(cpu);
 
-       if (! ((asid += ASID_INC) & ASID_MASK) ) {
+       if (!((asid += cpu_asid_inc()) & cpu_asid_mask(&cpu_data[cpu]))) {
                if (cpu_has_vtag_icache)
                        flush_icache_all();
 #ifdef CONFIG_KVM
@@ -113,7 +108,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
                local_flush_tlb_all();  /* start new asid cycle */
 #endif
                if (!asid)              /* fix version if needed */
-                       asid = ASID_FIRST_VERSION;
+                       asid = asid_first_version(cpu);
        }
 
        cpu_context(cpu, mm) = asid_cache(cpu) = asid;
@@ -145,7 +140,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
        htw_stop();
        /* Check if our ASID is of an older version and thus invalid */
-       if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
+       if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & asid_version_mask(cpu))
                get_new_mmu_context(next, cpu);
        write_c0_entryhi(cpu_asid(cpu, next));
        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
index bbb85fe21642f0e7f01b45bd4ba70076ed7a8b4c..6e4effa6f62611848831d8f48d793a96e5bfef71 100644 (file)
@@ -147,6 +147,19 @@ static inline void restore_msa(struct task_struct *t)
                _restore_msa(t);
 }
 
+static inline void init_msa_upper(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;
+
+       _init_msa_upper();
+}
+
 #ifdef TOOLCHAIN_SUPPORTS_MSA
 
 #define __BUILD_MSA_CTL_REG(name, cs)                          \
index d92cf59bdae63491201f247edb1bac5b1a30555e..62787765575efff0baee2c0b67f1c6fb4afcb51e 100644 (file)
@@ -32,6 +32,8 @@
 #ifndef __CVMX_BOOTINFO_H__
 #define __CVMX_BOOTINFO_H__
 
+#include "cvmx-coremask.h"
+
 /*
  * Current major and minor versions of the CVMX bootinfo block that is
  * passed from the bootloader to the application.  This is versioned
@@ -39,7 +41,7 @@
  * versions.
  */
 #define CVMX_BOOTINFO_MAJ_VER 1
-#define CVMX_BOOTINFO_MIN_VER 3
+#define CVMX_BOOTINFO_MIN_VER 4
 
 #if (CVMX_BOOTINFO_MAJ_VER == 1)
 #define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20
@@ -124,6 +126,13 @@ struct cvmx_bootinfo {
         */
        uint64_t fdt_addr;
 #endif
+#if (CVMX_BOOTINFO_MIN_VER >= 4)
+       /*
+        * Coremask used for processors with more than 32 cores
+        * or with OCI.  This replaces core_mask.
+        */
+       struct cvmx_coremask ext_core_mask;
+#endif
 #else                          /* __BIG_ENDIAN */
        /*
         * Little-Endian: When the CPU mode is switched to
@@ -177,6 +186,9 @@ struct cvmx_bootinfo {
 #if (CVMX_BOOTINFO_MIN_VER >= 3)
        uint64_t fdt_addr;
 #endif
+#if (CVMX_BOOTINFO_MIN_VER >= 4)
+       struct cvmx_coremask ext_core_mask;
+#endif
 #endif
 };
 
@@ -388,7 +400,7 @@ static inline const char *cvmx_board_type_to_string(enum
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901)
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
        }
-       return "Unsupported Board";
+       return NULL;
 }
 
 #define ENUM_CHIP_TYPE_CASE(x) \
diff --git a/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h b/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h
new file mode 100644 (file)
index 0000000..547f778
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2003-2016 Cavium Inc.
+ *
+ * This file 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.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+#ifndef __CVMX_CIU3_DEFS_H__
+#define __CVMX_CIU3_DEFS_H__
+
+#define CVMX_CIU3_FUSE CVMX_ADD_IO_SEG(0x00010100000001A0ull)
+#define CVMX_CIU3_BIST CVMX_ADD_IO_SEG(0x00010100000001C0ull)
+#define CVMX_CIU3_CONST CVMX_ADD_IO_SEG(0x0001010000000220ull)
+#define CVMX_CIU3_CTL CVMX_ADD_IO_SEG(0x00010100000000E0ull)
+#define CVMX_CIU3_DESTX_IO_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000210000ull) + ((offset) & 7) * 8)
+#define CVMX_CIU3_DESTX_PP_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000200000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_GSTOP CVMX_ADD_IO_SEG(0x0001010000000140ull)
+#define CVMX_CIU3_IDTX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010000110000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_IDTX_IO(offset) (CVMX_ADD_IO_SEG(0x0001010000130000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_IDTX_PPX(offset, block_id) (CVMX_ADD_IO_SEG(0x0001010000120000ull) + ((block_id) & 255) * 0x20ull)
+#define CVMX_CIU3_INTR_RAM_ECC_CTL CVMX_ADD_IO_SEG(0x0001010000000260ull)
+#define CVMX_CIU3_INTR_RAM_ECC_ST CVMX_ADD_IO_SEG(0x0001010000000280ull)
+#define CVMX_CIU3_INTR_READY CVMX_ADD_IO_SEG(0x00010100000002A0ull)
+#define CVMX_CIU3_INTR_SLOWDOWN CVMX_ADD_IO_SEG(0x0001010000000240ull)
+#define CVMX_CIU3_ISCX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010080000000ull) + ((offset) & 1048575) * 8)
+#define CVMX_CIU3_ISCX_W1C(offset) (CVMX_ADD_IO_SEG(0x0001010090000000ull) + ((offset) & 1048575) * 8)
+#define CVMX_CIU3_ISCX_W1S(offset) (CVMX_ADD_IO_SEG(0x00010100A0000000ull) + ((offset) & 1048575) * 8)
+#define CVMX_CIU3_NMI CVMX_ADD_IO_SEG(0x0001010000000160ull)
+#define CVMX_CIU3_SISCX(offset) (CVMX_ADD_IO_SEG(0x0001010000220000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_TIMX(offset) (CVMX_ADD_IO_SEG(0x0001010000010000ull) + ((offset) & 15) * 8)
+
+union cvmx_ciu3_bist {
+       uint64_t u64;
+       struct cvmx_ciu3_bist_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_9_63                : 55;
+       uint64_t bist                         : 9;
+#else
+       uint64_t bist                         : 9;
+       uint64_t reserved_9_63                : 55;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_const {
+       uint64_t u64;
+       struct cvmx_ciu3_const_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t dests_io                     : 16;
+       uint64_t pintsn                       : 16;
+       uint64_t dests_pp                     : 16;
+       uint64_t idt                          : 16;
+#else
+       uint64_t idt                          : 16;
+       uint64_t dests_pp                     : 16;
+       uint64_t pintsn                       : 16;
+       uint64_t dests_io                     : 16;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_ctl {
+       uint64_t u64;
+       struct cvmx_ciu3_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_5_63                : 59;
+       uint64_t mcd_sel                      : 2;
+       uint64_t iscmem_le                    : 1;
+       uint64_t seq_dis                      : 1;
+       uint64_t cclk_dis                     : 1;
+#else
+       uint64_t cclk_dis                     : 1;
+       uint64_t seq_dis                      : 1;
+       uint64_t iscmem_le                    : 1;
+       uint64_t mcd_sel                      : 2;
+       uint64_t reserved_5_63                : 59;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_destx_io_int {
+       uint64_t u64;
+       struct cvmx_ciu3_destx_io_int_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_52_63               : 12;
+       uint64_t intsn                        : 20;
+       uint64_t reserved_10_31               : 22;
+       uint64_t intidt                       : 8;
+       uint64_t newint                       : 1;
+       uint64_t intr                         : 1;
+#else
+       uint64_t intr                         : 1;
+       uint64_t newint                       : 1;
+       uint64_t intidt                       : 8;
+       uint64_t reserved_10_31               : 22;
+       uint64_t intsn                        : 20;
+       uint64_t reserved_52_63               : 12;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_destx_pp_int {
+       uint64_t u64;
+       struct cvmx_ciu3_destx_pp_int_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_52_63               : 12;
+       uint64_t intsn                        : 20;
+       uint64_t reserved_10_31               : 22;
+       uint64_t intidt                       : 8;
+       uint64_t newint                       : 1;
+       uint64_t intr                         : 1;
+#else
+       uint64_t intr                         : 1;
+       uint64_t newint                       : 1;
+       uint64_t intidt                       : 8;
+       uint64_t reserved_10_31               : 22;
+       uint64_t intsn                        : 20;
+       uint64_t reserved_52_63               : 12;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_gstop {
+       uint64_t u64;
+       struct cvmx_ciu3_gstop_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_1_63                : 63;
+       uint64_t gstop                        : 1;
+#else
+       uint64_t gstop                        : 1;
+       uint64_t reserved_1_63                : 63;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_idtx_ctl {
+       uint64_t u64;
+       struct cvmx_ciu3_idtx_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_52_63               : 12;
+       uint64_t intsn                        : 20;
+       uint64_t reserved_4_31                : 28;
+       uint64_t intr                         : 1;
+       uint64_t newint                       : 1;
+       uint64_t ip_num                       : 2;
+#else
+       uint64_t ip_num                       : 2;
+       uint64_t newint                       : 1;
+       uint64_t intr                         : 1;
+       uint64_t reserved_4_31                : 28;
+       uint64_t intsn                        : 20;
+       uint64_t reserved_52_63               : 12;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_idtx_io {
+       uint64_t u64;
+       struct cvmx_ciu3_idtx_io_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_5_63                : 59;
+       uint64_t io                           : 5;
+#else
+       uint64_t io                           : 5;
+       uint64_t reserved_5_63                : 59;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_idtx_ppx {
+       uint64_t u64;
+       struct cvmx_ciu3_idtx_ppx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_48_63               : 16;
+       uint64_t pp                           : 48;
+#else
+       uint64_t pp                           : 48;
+       uint64_t reserved_48_63               : 16;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_intr_ram_ecc_ctl {
+       uint64_t u64;
+       struct cvmx_ciu3_intr_ram_ecc_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_3_63                : 61;
+       uint64_t flip_synd                    : 2;
+       uint64_t ecc_ena                      : 1;
+#else
+       uint64_t ecc_ena                      : 1;
+       uint64_t flip_synd                    : 2;
+       uint64_t reserved_3_63                : 61;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_intr_ram_ecc_st {
+       uint64_t u64;
+       struct cvmx_ciu3_intr_ram_ecc_st_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_52_63               : 12;
+       uint64_t addr                         : 20;
+       uint64_t reserved_6_31                : 26;
+       uint64_t sisc_dbe                     : 1;
+       uint64_t sisc_sbe                     : 1;
+       uint64_t idt_dbe                      : 1;
+       uint64_t idt_sbe                      : 1;
+       uint64_t isc_dbe                      : 1;
+       uint64_t isc_sbe                      : 1;
+#else
+       uint64_t isc_sbe                      : 1;
+       uint64_t isc_dbe                      : 1;
+       uint64_t idt_sbe                      : 1;
+       uint64_t idt_dbe                      : 1;
+       uint64_t sisc_sbe                     : 1;
+       uint64_t sisc_dbe                     : 1;
+       uint64_t reserved_6_31                : 26;
+       uint64_t addr                         : 20;
+       uint64_t reserved_52_63               : 12;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_intr_ready {
+       uint64_t u64;
+       struct cvmx_ciu3_intr_ready_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_46_63               : 18;
+       uint64_t index                        : 14;
+       uint64_t reserved_1_31                : 31;
+       uint64_t ready                        : 1;
+#else
+       uint64_t ready                        : 1;
+       uint64_t reserved_1_31                : 31;
+       uint64_t index                        : 14;
+       uint64_t reserved_46_63               : 18;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_intr_slowdown {
+       uint64_t u64;
+       struct cvmx_ciu3_intr_slowdown_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_3_63                : 61;
+       uint64_t ctl                          : 3;
+#else
+       uint64_t ctl                          : 3;
+       uint64_t reserved_3_63                : 61;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_iscx_ctl {
+       uint64_t u64;
+       struct cvmx_ciu3_iscx_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_24_63               : 40;
+       uint64_t idt                          : 8;
+       uint64_t imp                          : 1;
+       uint64_t reserved_2_14                : 13;
+       uint64_t en                           : 1;
+       uint64_t raw                          : 1;
+#else
+       uint64_t raw                          : 1;
+       uint64_t en                           : 1;
+       uint64_t reserved_2_14                : 13;
+       uint64_t imp                          : 1;
+       uint64_t idt                          : 8;
+       uint64_t reserved_24_63               : 40;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_iscx_w1c {
+       uint64_t u64;
+       struct cvmx_ciu3_iscx_w1c_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_2_63                : 62;
+       uint64_t en                           : 1;
+       uint64_t raw                          : 1;
+#else
+       uint64_t raw                          : 1;
+       uint64_t en                           : 1;
+       uint64_t reserved_2_63                : 62;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_iscx_w1s {
+       uint64_t u64;
+       struct cvmx_ciu3_iscx_w1s_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_2_63                : 62;
+       uint64_t en                           : 1;
+       uint64_t raw                          : 1;
+#else
+       uint64_t raw                          : 1;
+       uint64_t en                           : 1;
+       uint64_t reserved_2_63                : 62;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_nmi {
+       uint64_t u64;
+       struct cvmx_ciu3_nmi_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_48_63               : 16;
+       uint64_t nmi                          : 48;
+#else
+       uint64_t nmi                          : 48;
+       uint64_t reserved_48_63               : 16;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_siscx {
+       uint64_t u64;
+       struct cvmx_ciu3_siscx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t en                           : 64;
+#else
+       uint64_t en                           : 64;
+#endif
+       } s;
+};
+
+union cvmx_ciu3_timx {
+       uint64_t u64;
+       struct cvmx_ciu3_timx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint64_t reserved_37_63               : 27;
+       uint64_t one_shot                     : 1;
+       uint64_t len                          : 36;
+#else
+       uint64_t len                          : 36;
+       uint64_t one_shot                     : 1;
+       uint64_t reserved_37_63               : 27;
+#endif
+       } s;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-coremask.h b/arch/mips/include/asm/octeon/cvmx-coremask.h
new file mode 100644 (file)
index 0000000..097dc09
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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) 2016  Cavium Inc. (support@cavium.com).
+ *
+ */
+
+/*
+ * Module to support operations on bitmap of cores. Coremask can be used to
+ * select a specific core, a group of cores, or all available cores, for
+ * initialization and differentiation of roles within a single shared binary
+ * executable image.
+ *
+ * The core numbers used in this file are the same value as what is found in
+ * the COP0_EBASE register and the rdhwr 0 instruction.
+ *
+ * For the CN78XX and other multi-node environments the core numbers are not
+ * contiguous.  The core numbers for the CN78XX are as follows:
+ *
+ * Node 0:     Cores 0 - 47
+ * Node 1:     Cores 128 - 175
+ * Node 2:     Cores 256 - 303
+ * Node 3:     Cores 384 - 431
+ *
+ */
+
+#ifndef __CVMX_COREMASK_H__
+#define __CVMX_COREMASK_H__
+
+#define CVMX_MIPS_MAX_CORES 1024
+/* bits per holder */
+#define CVMX_COREMASK_ELTSZ 64
+
+/* cvmx_coremask_t's size in u64 */
+#define CVMX_COREMASK_BMPSZ (CVMX_MIPS_MAX_CORES / CVMX_COREMASK_ELTSZ)
+
+
+/* cvmx_coremask_t */
+struct cvmx_coremask {
+       u64 coremask_bitmap[CVMX_COREMASK_BMPSZ];
+};
+
+/*
+ * Is ``core'' set in the coremask?
+ */
+static inline bool cvmx_coremask_is_core_set(const struct cvmx_coremask *pcm,
+                                           int core)
+{
+       int n, i;
+
+       n = core % CVMX_COREMASK_ELTSZ;
+       i = core / CVMX_COREMASK_ELTSZ;
+
+       return (pcm->coremask_bitmap[i] & ((u64)1 << n)) != 0;
+}
+
+/*
+ * Make a copy of a coremask
+ */
+static inline void cvmx_coremask_copy(struct cvmx_coremask *dest,
+                                     const struct cvmx_coremask *src)
+{
+       memcpy(dest, src, sizeof(*dest));
+}
+
+/*
+ * Set the lower 64-bit of the coremask.
+ */
+static inline void cvmx_coremask_set64(struct cvmx_coremask *pcm,
+                                      uint64_t coremask_64)
+{
+       pcm->coremask_bitmap[0] = coremask_64;
+}
+
+/*
+ * Clear ``core'' from the coremask.
+ */
+static inline void cvmx_coremask_clear_core(struct cvmx_coremask *pcm, int core)
+{
+       int n, i;
+
+       n = core % CVMX_COREMASK_ELTSZ;
+       i = core / CVMX_COREMASK_ELTSZ;
+       pcm->coremask_bitmap[i] &= ~(1ull << n);
+}
+
+#endif /* __CVMX_COREMASK_H__ */
index 1d79e3c7040d17891a34d5907179e56487a33a6d..887ff8e1f715d02defd4bc691f6e8b595a5368f3 100644 (file)
@@ -66,6 +66,7 @@
 #define CVMX_FPA_WART_CTL (CVMX_ADD_IO_SEG(0x00011800280000D8ull))
 #define CVMX_FPA_WART_STATUS (CVMX_ADD_IO_SEG(0x00011800280000E0ull))
 #define CVMX_FPA_WQE_THRESHOLD (CVMX_ADD_IO_SEG(0x0001180028000468ull))
+#define CVMX_FPA_CLK_COUNT (CVMX_ADD_IO_SEG(0x00012800000000F0ull))
 
 union cvmx_fpa_addr_range_error {
        uint64_t u64;
index bb0ae338a4600cb7d31cd58576b5b1bf96a7d8e7..5196c04eee4116752174b720923f84addd98a149 100644 (file)
@@ -1481,7 +1481,9 @@ union cvmx_mio_fus_dat2 {
        uint64_t u64;
        struct cvmx_mio_fus_dat2_s {
 #ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_48_63:16;
+               uint64_t reserved_59_63:5;
+               uint64_t run_platform:3;
+               uint64_t gbl_pwr_throttle:8;
                uint64_t fus118:1;
                uint64_t rom_info:10;
                uint64_t power_limit:2;
@@ -1513,7 +1515,9 @@ union cvmx_mio_fus_dat2 {
                uint64_t power_limit:2;
                uint64_t rom_info:10;
                uint64_t fus118:1;
-               uint64_t reserved_48_63:16;
+               uint64_t gbl_pwr_throttle:8;
+               uint64_t run_platform:3;
+               uint64_t reserved_59_63:5;
 #endif
        } s;
        struct cvmx_mio_fus_dat2_cn30xx {
@@ -1837,50 +1841,192 @@ union cvmx_mio_fus_dat2 {
 #endif
        } cn68xx;
        struct cvmx_mio_fus_dat2_cn68xx cn68xxp1;
+       struct cvmx_mio_fus_dat2_cn70xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_48_63:16;
+               uint64_t fus118:1;
+               uint64_t rom_info:10;
+               uint64_t power_limit:2;
+               uint64_t dorm_crypto:1;
+               uint64_t fus318:1;
+               uint64_t raid_en:1;
+               uint64_t reserved_31_29:3;
+               uint64_t nodfa_cp2:1;
+               uint64_t nomul:1;
+               uint64_t nocrypto:1;
+               uint64_t reserved_25_24:2;
+               uint64_t chip_id:8;
+               uint64_t reserved_15_0:16;
+#else
+               uint64_t reserved_15_0:16;
+               uint64_t chip_id:8;
+               uint64_t reserved_25_24:2;
+               uint64_t nocrypto:1;
+               uint64_t nomul:1;
+               uint64_t nodfa_cp2:1;
+               uint64_t reserved_31_29:3;
+               uint64_t raid_en:1;
+               uint64_t fus318:1;
+               uint64_t dorm_crypto:1;
+               uint64_t power_limit:2;
+               uint64_t rom_info:10;
+               uint64_t fus118:1;
+               uint64_t reserved_48_63:16;
+#endif
+       } cn70xx;
+       struct cvmx_mio_fus_dat2_cn70xx cn70xxp1;
+       struct cvmx_mio_fus_dat2_cn73xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_59_63:5;
+               uint64_t run_platform:3;
+               uint64_t gbl_pwr_throttle:8;
+               uint64_t fus118:1;
+               uint64_t rom_info:10;
+               uint64_t power_limit:2;
+               uint64_t dorm_crypto:1;
+               uint64_t fus318:1;
+               uint64_t raid_en:1;
+               uint64_t reserved_31_29:3;
+               uint64_t nodfa_cp2:1;
+               uint64_t nomul:1;
+               uint64_t nocrypto:1;
+               uint64_t reserved_25_24:2;
+               uint64_t chip_id:8;
+               uint64_t reserved_15_0:16;
+#else
+               uint64_t reserved_15_0:16;
+               uint64_t chip_id:8;
+               uint64_t reserved_25_24:2;
+               uint64_t nocrypto:1;
+               uint64_t nomul:1;
+               uint64_t nodfa_cp2:1;
+               uint64_t reserved_31_29:3;
+               uint64_t raid_en:1;
+               uint64_t fus318:1;
+               uint64_t dorm_crypto:1;
+               uint64_t power_limit:2;
+               uint64_t rom_info:10;
+               uint64_t fus118:1;
+               uint64_t gbl_pwr_throttle:8;
+               uint64_t run_platform:3;
+               uint64_t reserved_59_63:5;
+#endif
+       } cn73xx;
+       struct cvmx_mio_fus_dat2_cn78xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_59_63:5;
+               uint64_t run_platform:3;
+               uint64_t reserved_48_55:8;
+               uint64_t fus118:1;
+               uint64_t rom_info:10;
+               uint64_t power_limit:2;
+               uint64_t dorm_crypto:1;
+               uint64_t fus318:1;
+               uint64_t raid_en:1;
+               uint64_t reserved_31_29:3;
+               uint64_t nodfa_cp2:1;
+               uint64_t nomul:1;
+               uint64_t nocrypto:1;
+               uint64_t reserved_25_24:2;
+               uint64_t chip_id:8;
+               uint64_t reserved_0_15:16;
+#else
+               uint64_t reserved_0_15:16;
+               uint64_t chip_id:8;
+               uint64_t reserved_25_24:2;
+               uint64_t nocrypto:1;
+               uint64_t nomul:1;
+               uint64_t nodfa_cp2:1;
+               uint64_t reserved_31_29:3;
+               uint64_t raid_en:1;
+               uint64_t fus318:1;
+               uint64_t dorm_crypto:1;
+               uint64_t power_limit:2;
+               uint64_t rom_info:10;
+               uint64_t fus118:1;
+               uint64_t reserved_48_55:8;
+               uint64_t run_platform:3;
+               uint64_t reserved_59_63:5;
+#endif
+       } cn78xx;
+       struct cvmx_mio_fus_dat2_cn78xxp2 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t reserved_59_63:5;
+               uint64_t run_platform:3;
+               uint64_t gbl_pwr_throttle:8;
+               uint64_t fus118:1;
+               uint64_t rom_info:10;
+               uint64_t power_limit:2;
+               uint64_t dorm_crypto:1;
+               uint64_t fus318:1;
+               uint64_t raid_en:1;
+               uint64_t reserved_31_29:3;
+               uint64_t nodfa_cp2:1;
+               uint64_t nomul:1;
+               uint64_t nocrypto:1;
+               uint64_t reserved_25_24:2;
+               uint64_t chip_id:8;
+               uint64_t reserved_0_15:16;
+#else
+               uint64_t reserved_0_15:16;
+               uint64_t chip_id:8;
+               uint64_t reserved_25_24:2;
+               uint64_t nocrypto:1;
+               uint64_t nomul:1;
+               uint64_t nodfa_cp2:1;
+               uint64_t reserved_31_29:3;
+               uint64_t raid_en:1;
+               uint64_t fus318:1;
+               uint64_t dorm_crypto:1;
+               uint64_t power_limit:2;
+               uint64_t rom_info:10;
+               uint64_t fus118:1;
+               uint64_t gbl_pwr_throttle:8;
+               uint64_t run_platform:3;
+               uint64_t reserved_59_63:5;
+#endif
+       } cn78xxp2;
        struct cvmx_mio_fus_dat2_cn61xx cnf71xx;
+       struct cvmx_mio_fus_dat2_cn73xx cnf75xx;
 };
 
 union cvmx_mio_fus_dat3 {
        uint64_t u64;
        struct cvmx_mio_fus_dat3_s {
 #ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_58_63:6;
+               uint64_t ema0:6;
                uint64_t pll_ctl:10;
                uint64_t dfa_info_dte:3;
                uint64_t dfa_info_clm:4;
-               uint64_t reserved_40_40:1;
-               uint64_t ema:2;
+               uint64_t pll_alt_matrix:1;
+               uint64_t reserved_38_39:2;
                uint64_t efus_lck_rsv:1;
                uint64_t efus_lck_man:1;
                uint64_t pll_half_dis:1;
                uint64_t l2c_crip:3;
-               uint64_t pll_div4:1;
-               uint64_t reserved_29_30:2;
-               uint64_t bar2_en:1;
+               uint64_t reserved_28_31:4;
                uint64_t efus_lck:1;
                uint64_t efus_ign:1;
                uint64_t nozip:1;
                uint64_t nodfa_dte:1;
-               uint64_t icache:24;
+               uint64_t reserved_0_23:24;
 #else
-               uint64_t icache:24;
+               uint64_t reserved_0_23:24;
                uint64_t nodfa_dte:1;
                uint64_t nozip:1;
                uint64_t efus_ign:1;
                uint64_t efus_lck:1;
-               uint64_t bar2_en:1;
-               uint64_t reserved_29_30:2;
-               uint64_t pll_div4:1;
+               uint64_t reserved_28_31:4;
                uint64_t l2c_crip:3;
                uint64_t pll_half_dis:1;
                uint64_t efus_lck_man:1;
                uint64_t efus_lck_rsv:1;
-               uint64_t ema:2;
-               uint64_t reserved_40_40:1;
+               uint64_t reserved_38_39:2;
+               uint64_t pll_alt_matrix:1;
                uint64_t dfa_info_clm:4;
                uint64_t dfa_info_dte:3;
                uint64_t pll_ctl:10;
-               uint64_t reserved_58_63:6;
+               uint64_t ema0:6;
 #endif
        } s;
        struct cvmx_mio_fus_dat3_cn30xx {
@@ -2022,7 +2168,239 @@ union cvmx_mio_fus_dat3 {
        struct cvmx_mio_fus_dat3_cn61xx cn66xx;
        struct cvmx_mio_fus_dat3_cn61xx cn68xx;
        struct cvmx_mio_fus_dat3_cn61xx cn68xxp1;
+       struct cvmx_mio_fus_dat3_cn70xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t ema0:6;
+               uint64_t pll_ctl:10;
+               uint64_t dfa_info_dte:3;
+               uint64_t dfa_info_clm:4;
+               uint64_t pll_alt_matrix:1;
+               uint64_t pll_bwadj_denom:2;
+               uint64_t efus_lck_rsv:1;
+               uint64_t efus_lck_man:1;
+               uint64_t pll_half_dis:1;
+               uint64_t l2c_crip:3;
+               uint64_t use_int_refclk:1;
+               uint64_t zip_info:2;
+               uint64_t bar2_sz_conf:1;
+               uint64_t efus_lck:1;
+               uint64_t efus_ign:1;
+               uint64_t nozip:1;
+               uint64_t nodfa_dte:1;
+               uint64_t ema1:6;
+               uint64_t reserved_0_17:18;
+#else
+               uint64_t reserved_0_17:18;
+               uint64_t ema1:6;
+               uint64_t nodfa_dte:1;
+               uint64_t nozip:1;
+               uint64_t efus_ign:1;
+               uint64_t efus_lck:1;
+               uint64_t bar2_sz_conf:1;
+               uint64_t zip_info:2;
+               uint64_t use_int_refclk:1;
+               uint64_t l2c_crip:3;
+               uint64_t pll_half_dis:1;
+               uint64_t efus_lck_man:1;
+               uint64_t efus_lck_rsv:1;
+               uint64_t pll_bwadj_denom:2;
+               uint64_t pll_alt_matrix:1;
+               uint64_t dfa_info_clm:4;
+               uint64_t dfa_info_dte:3;
+               uint64_t pll_ctl:10;
+               uint64_t ema0:6;
+#endif
+       } cn70xx;
+       struct cvmx_mio_fus_dat3_cn70xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t ema0:6;
+               uint64_t pll_ctl:10;
+               uint64_t dfa_info_dte:3;
+               uint64_t dfa_info_clm:4;
+               uint64_t reserved_38_40:3;
+               uint64_t efus_lck_rsv:1;
+               uint64_t efus_lck_man:1;
+               uint64_t pll_half_dis:1;
+               uint64_t l2c_crip:3;
+               uint64_t reserved_31_31:1;
+               uint64_t zip_info:2;
+               uint64_t bar2_sz_conf:1;
+               uint64_t efus_lck:1;
+               uint64_t efus_ign:1;
+               uint64_t nozip:1;
+               uint64_t nodfa_dte:1;
+               uint64_t ema1:6;
+               uint64_t reserved_0_17:18;
+#else
+               uint64_t reserved_0_17:18;
+               uint64_t ema1:6;
+               uint64_t nodfa_dte:1;
+               uint64_t nozip:1;
+               uint64_t efus_ign:1;
+               uint64_t efus_lck:1;
+               uint64_t bar2_sz_conf:1;
+               uint64_t zip_info:2;
+               uint64_t reserved_31_31:1;
+               uint64_t l2c_crip:3;
+               uint64_t pll_half_dis:1;
+               uint64_t efus_lck_man:1;
+               uint64_t efus_lck_rsv:1;
+               uint64_t reserved_38_40:3;
+               uint64_t dfa_info_clm:4;
+               uint64_t dfa_info_dte:3;
+               uint64_t pll_ctl:10;
+               uint64_t ema0:6;
+#endif
+       } cn70xxp1;
+       struct cvmx_mio_fus_dat3_cn73xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t ema0:6;
+               uint64_t pll_ctl:10;
+               uint64_t dfa_info_dte:3;
+               uint64_t dfa_info_clm:4;
+               uint64_t pll_alt_matrix:1;
+               uint64_t pll_bwadj_denom:2;
+               uint64_t efus_lck_rsv:1;
+               uint64_t efus_lck_man:1;
+               uint64_t pll_half_dis:1;
+               uint64_t l2c_crip:3;
+               uint64_t use_int_refclk:1;
+               uint64_t zip_info:2;
+               uint64_t bar2_sz_conf:1;
+               uint64_t efus_lck:1;
+               uint64_t efus_ign:1;
+               uint64_t nozip:1;
+               uint64_t nodfa_dte:1;
+               uint64_t ema1:6;
+               uint64_t nohna_dte:1;
+               uint64_t hna_info_dte:3;
+               uint64_t hna_info_clm:4;
+               uint64_t reserved_9_9:1;
+               uint64_t core_pll_mul:5;
+               uint64_t pnr_pll_mul:4;
+#else
+               uint64_t pnr_pll_mul:4;
+               uint64_t core_pll_mul:5;
+               uint64_t reserved_9_9:1;
+               uint64_t hna_info_clm:4;
+               uint64_t hna_info_dte:3;
+               uint64_t nohna_dte:1;
+               uint64_t ema1:6;
+               uint64_t nodfa_dte:1;
+               uint64_t nozip:1;
+               uint64_t efus_ign:1;
+               uint64_t efus_lck:1;
+               uint64_t bar2_sz_conf:1;
+               uint64_t zip_info:2;
+               uint64_t use_int_refclk:1;
+               uint64_t l2c_crip:3;
+               uint64_t pll_half_dis:1;
+               uint64_t efus_lck_man:1;
+               uint64_t efus_lck_rsv:1;
+               uint64_t pll_bwadj_denom:2;
+               uint64_t pll_alt_matrix:1;
+               uint64_t dfa_info_clm:4;
+               uint64_t dfa_info_dte:3;
+               uint64_t pll_ctl:10;
+               uint64_t ema0:6;
+#endif
+       } cn73xx;
+       struct cvmx_mio_fus_dat3_cn78xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t ema0:6;
+               uint64_t pll_ctl:10;
+               uint64_t dfa_info_dte:3;
+               uint64_t dfa_info_clm:4;
+               uint64_t reserved_38_40:3;
+               uint64_t efus_lck_rsv:1;
+               uint64_t efus_lck_man:1;
+               uint64_t pll_half_dis:1;
+               uint64_t l2c_crip:3;
+               uint64_t reserved_31_31:1;
+               uint64_t zip_info:2;
+               uint64_t bar2_sz_conf:1;
+               uint64_t efus_lck:1;
+               uint64_t efus_ign:1;
+               uint64_t nozip:1;
+               uint64_t nodfa_dte:1;
+               uint64_t ema1:6;
+               uint64_t nohna_dte:1;
+               uint64_t hna_info_dte:3;
+               uint64_t hna_info_clm:4;
+               uint64_t reserved_0_9:10;
+#else
+               uint64_t reserved_0_9:10;
+               uint64_t hna_info_clm:4;
+               uint64_t hna_info_dte:3;
+               uint64_t nohna_dte:1;
+               uint64_t ema1:6;
+               uint64_t nodfa_dte:1;
+               uint64_t nozip:1;
+               uint64_t efus_ign:1;
+               uint64_t efus_lck:1;
+               uint64_t bar2_sz_conf:1;
+               uint64_t zip_info:2;
+               uint64_t reserved_31_31:1;
+               uint64_t l2c_crip:3;
+               uint64_t pll_half_dis:1;
+               uint64_t efus_lck_man:1;
+               uint64_t efus_lck_rsv:1;
+               uint64_t reserved_38_40:3;
+               uint64_t dfa_info_clm:4;
+               uint64_t dfa_info_dte:3;
+               uint64_t pll_ctl:10;
+               uint64_t ema0:6;
+#endif
+       } cn78xx;
+       struct cvmx_mio_fus_dat3_cn73xx cn78xxp2;
        struct cvmx_mio_fus_dat3_cn61xx cnf71xx;
+       struct cvmx_mio_fus_dat3_cnf75xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+               uint64_t ema0:6;
+               uint64_t pll_ctl:10;
+               uint64_t dfa_info_dte:3;
+               uint64_t dfa_info_clm:4;
+               uint64_t pll_alt_matrix:1;
+               uint64_t pll_bwadj_denom:2;
+               uint64_t efus_lck_rsv:1;
+               uint64_t efus_lck_man:1;
+               uint64_t pll_half_dis:1;
+               uint64_t l2c_crip:3;
+               uint64_t use_int_refclk:1;
+               uint64_t zip_info:2;
+               uint64_t bar2_sz_conf:1;
+               uint64_t efus_lck:1;
+               uint64_t efus_ign:1;
+               uint64_t nozip:1;
+               uint64_t nodfa_dte:1;
+               uint64_t ema1:6;
+               uint64_t reserved_9_17:9;
+               uint64_t core_pll_mul:5;
+               uint64_t pnr_pll_mul:4;
+#else
+               uint64_t pnr_pll_mul:4;
+               uint64_t core_pll_mul:5;
+               uint64_t reserved_9_17:9;
+               uint64_t ema1:6;
+               uint64_t nodfa_dte:1;
+               uint64_t nozip:1;
+               uint64_t efus_ign:1;
+               uint64_t efus_lck:1;
+               uint64_t bar2_sz_conf:1;
+               uint64_t zip_info:2;
+               uint64_t use_int_refclk:1;
+               uint64_t l2c_crip:3;
+               uint64_t pll_half_dis:1;
+               uint64_t efus_lck_man:1;
+               uint64_t efus_lck_rsv:1;
+               uint64_t pll_bwadj_denom:2;
+               uint64_t pll_alt_matrix:1;
+               uint64_t dfa_info_clm:4;
+               uint64_t dfa_info_dte:3;
+               uint64_t pll_ctl:10;
+               uint64_t ema0:6;
+#endif
+       } cnf75xx;
 };
 
 union cvmx_mio_fus_ema {
index 2131197422e5202a11ac4b8f6e518bbd88f48781..c6c3ee39c69d6a8c9643de8aede1eeba2d648878 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2008 Cavium Networks
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
@@ -32,6 +32,8 @@
 #ifndef __CVMX_SYSINFO_H__
 #define __CVMX_SYSINFO_H__
 
+#include "cvmx-coremask.h"
+
 #define OCTEON_SERIAL_LEN 20
 /**
  * Structure describing application specific information.
@@ -50,8 +52,7 @@ struct cvmx_sysinfo {
        uint64_t system_dram_size;
 
        /* ptr to memory descriptor block */
-       void *phy_mem_desc_ptr;
-
+       uint64_t phy_mem_desc_addr;
 
        /* Application image specific variables */
        /* stack top address (virtual) */
@@ -63,7 +64,7 @@ struct cvmx_sysinfo {
        /* heap size in bytes */
        uint32_t heap_size;
        /* coremask defining cores running application */
-       uint32_t core_mask;
+       struct cvmx_coremask core_mask;
        /* Deprecated, use cvmx_coremask_first_core() to select init core */
        uint32_t init_core;
 
@@ -121,32 +122,4 @@ struct cvmx_sysinfo {
 
 extern struct cvmx_sysinfo *cvmx_sysinfo_get(void);
 
-/**
- * This function is used in non-simple executive environments (such as
- * Linux kernel, u-boot, etc.) to configure the minimal fields that
- * are required to use simple executive files directly.
- *
- * Locking (if required) must be handled outside of this
- * function
- *
- * @phy_mem_desc_ptr: Pointer to global physical memory descriptor
- *                  (bootmem descriptor) @board_type: Octeon board
- *                  type enumeration
- *
- * @board_rev_major:
- *                  Board major revision
- * @board_rev_minor:
- *                  Board minor revision
- * @cpu_clock_hz:
- *                  CPU clock freqency in hertz
- *
- * Returns 0: Failure
- *        1: success
- */
-extern int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr,
-                                          uint16_t board_type,
-                                          uint8_t board_rev_major,
-                                          uint8_t board_rev_minor,
-                                          uint32_t cpu_clock_hz);
-
 #endif /* __CVMX_SYSINFO_H__ */
index 3e982e0c397e8a5d77d32c592d621bd1c31650c3..2530e8731c8abd09cf4e438156c43881da60494f 100644 (file)
@@ -57,6 +57,7 @@ enum cvmx_mips_space {
 #include <asm/octeon/cvmx-sysinfo.h>
 
 #include <asm/octeon/cvmx-ciu-defs.h>
+#include <asm/octeon/cvmx-ciu3-defs.h>
 #include <asm/octeon/cvmx-gpio-defs.h>
 #include <asm/octeon/cvmx-iob-defs.h>
 #include <asm/octeon/cvmx-ipd-defs.h>
@@ -341,6 +342,21 @@ static inline unsigned int cvmx_get_core_num(void)
        return core_num;
 }
 
+/* Maximum # of bits to define core in node */
+#define CVMX_NODE_NO_SHIFT     7
+#define CVMX_NODE_MASK         0x3
+static inline unsigned int cvmx_get_node_num(void)
+{
+       unsigned int core_num = cvmx_get_core_num();
+
+       return (core_num >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK;
+}
+
+static inline unsigned int cvmx_get_local_core_num(void)
+{
+       return cvmx_get_core_num() & ((1 << CVMX_NODE_NO_SHIFT) - 1);
+}
+
 /**
  * Returns the number of bits set in the provided value.
  * Simple wrapper for POP instruction.
@@ -448,8 +464,15 @@ static inline uint64_t cvmx_get_cycle_global(void)
 /* Return the number of cores available in the chip */
 static inline uint32_t cvmx_octeon_num_cores(void)
 {
-       uint32_t ciu_fuse = (uint32_t) cvmx_read_csr(CVMX_CIU_FUSE) & 0xffff;
-       return cvmx_pop(ciu_fuse);
+       u64 ciu_fuse_reg;
+       u64 ciu_fuse;
+
+       if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX))
+               ciu_fuse_reg = CVMX_CIU3_FUSE;
+       else
+               ciu_fuse_reg = CVMX_CIU_FUSE;
+       ciu_fuse = cvmx_read_csr(ciu_fuse_reg);
+       return cvmx_dpop(ciu_fuse);
 }
 
 #endif /*  __CVMX_H__  */
index 3ed10a8d78651373a55e4f99c722767cbbc26810..a19ca3b2775c8fb75d24103649deb13af3944459 100644 (file)
@@ -81,6 +81,10 @@ enum octeon_feature {
        OCTEON_FEATURE_HFA,
        OCTEON_FEATURE_DFM,
        OCTEON_FEATURE_CIU2,
+       OCTEON_FEATURE_CIU3,
+       /* Octeon has FPA first seen on 78XX */
+       OCTEON_FEATURE_FPA3,
+       OCTEON_FEATURE_FAU,
        OCTEON_MAX_FEATURE
 };
 
@@ -110,7 +114,7 @@ static inline int octeon_has_crypto(void)
  * Returns Non zero if the feature exists. Zero if the feature does not
  *        exist.
  */
-static inline int octeon_has_feature(enum octeon_feature feature)
+static inline bool octeon_has_feature(enum octeon_feature feature)
 {
        switch (feature) {
        case OCTEON_FEATURE_SAAD:
@@ -122,7 +126,7 @@ static inline int octeon_has_feature(enum octeon_feature feature)
                        fus_2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
                        return !fus_2.s.nocrypto && !fus_2.s.nomul && fus_2.s.dorm_crypto;
                } else {
-                       return 0;
+                       return false;
                }
 
        case OCTEON_FEATURE_PCIE:
@@ -190,11 +194,20 @@ static inline int octeon_has_feature(enum octeon_feature feature)
 
        case OCTEON_FEATURE_CIU2:
                return OCTEON_IS_MODEL(OCTEON_CN68XX);
+       case OCTEON_FEATURE_CIU3:
+       case OCTEON_FEATURE_FPA3:
+               return OCTEON_IS_MODEL(OCTEON_CN78XX)
+                       || OCTEON_IS_MODEL(OCTEON_CNF75XX)
+                       || OCTEON_IS_MODEL(OCTEON_CN73XX);
+       case OCTEON_FEATURE_FAU:
+               return !(OCTEON_IS_MODEL(OCTEON_CN78XX)
+                        || OCTEON_IS_MODEL(OCTEON_CNF75XX)
+                        || OCTEON_IS_MODEL(OCTEON_CN73XX));
 
        default:
                break;
        }
-       return 0;
+       return false;
 }
 
 #endif /* __OCTEON_FEATURE_H__ */
index 92b377e36dac260f9100d9178fe2252bed85e061..6c68517c2770274c966a5b0680de1ebd2e1a1378 100644 (file)
  * CN7XXX models with new revision encoding
  */
 
+#define OCTEON_CNF75XX_PASS1_0 0x000d9800
+#define OCTEON_CNF75XX         (OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_REVISION)
+#define OCTEON_CNF75XX_PASS1_X (OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
+
 #define OCTEON_CN73XX_PASS1_0  0x000d9700
+#define OCTEON_CN73XX_PASS1_1  0x000d9701
 #define OCTEON_CN73XX          (OCTEON_CN73XX_PASS1_0 | OM_IGNORE_REVISION)
 #define OCTEON_CN73XX_PASS1_X  (OCTEON_CN73XX_PASS1_0 | \
                                 OM_IGNORE_MINOR_REVISION)
index de9f74ee5dd0d2ace8165085918ea49d38f6242d..07c0516ef4d5331096be4dd45182ed938a9a96d3 100644 (file)
@@ -299,6 +299,31 @@ static inline void octeon_npi_write32(uint64_t address, uint32_t val)
        cvmx_read64_uint32(address ^ 4);
 }
 
+#ifdef CONFIG_SMP
+void octeon_setup_smp(void);
+#else
+static inline void octeon_setup_smp(void) {}
+#endif
+
+struct irq_domain;
+struct device_node;
+struct irq_data;
+struct irq_chip;
+void octeon_ciu3_mbox_send(int cpu, unsigned int mbox);
+int octeon_irq_ciu3_xlat(struct irq_domain *d,
+                        struct device_node *node,
+                        const u32 *intspec,
+                        unsigned int intsize,
+                        unsigned long *out_hwirq,
+                        unsigned int *out_type);
+void octeon_irq_ciu3_enable(struct irq_data *data);
+void octeon_irq_ciu3_disable(struct irq_data *data);
+void octeon_irq_ciu3_ack(struct irq_data *data);
+void octeon_irq_ciu3_mask(struct irq_data *data);
+void octeon_irq_ciu3_mask_ack(struct irq_data *data);
+int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq,
+                        irq_hw_number_t hw, struct irq_chip *chip);
+
 /* Octeon multiplier save/restore routines from octeon_switch.S */
 void octeon_mult_save(void);
 void octeon_mult_restore(void);
index 8c16fb7b8fdbefd6fa9db170d4d1254bf44a9e4c..86b239d9d75d3e6bfb75ec020d26e8e49bc4798b 100644 (file)
@@ -43,8 +43,6 @@ struct pci_controller {
           and XFree86. Eventually will be removed. */
        unsigned int need_domain_info;
 
-       int iommu;
-
        /* Optional access methods for reading/writing the bus number
           of the PCI controller */
        int (*get_busno)(void);
@@ -106,11 +104,11 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
 struct pci_dev;
 
 /*
- * The PCI address space does equal the physical memory address space. The
- * networking and block device layers use this boolean for bounce buffer
- * decisions.  This is set if any hose does not have an IOMMU.
+ * The PCI address space does equal the physical memory address space.
+ * The networking and block device layers use this boolean for bounce
+ * buffer decisions.
  */
-extern unsigned int PCI_DMA_BUS_IS_PHYS;
+#define PCI_DMA_BUS_IS_PHYS     (1)
 
 #ifdef CONFIG_PCI_DOMAINS
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
index 832e2167d00f8aa9987226c8bb5868b013fc878a..d21f3da7bdb619402a438b923fda454b7525d204 100644 (file)
@@ -103,8 +103,8 @@ static inline void pmd_clear(pmd_t *pmdp)
        pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
 }
 
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
-#define pte_page(x)            pfn_to_page(pte_pfn(x))
+#if defined(CONFIG_XPA)
+
 #define pte_pfn(x)             (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT))
 static inline pte_t
 pfn_pte(unsigned long pfn, pgprot_t prot)
@@ -118,9 +118,21 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
        return pte;
 }
 
-#else
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
-#define pte_page(x)            pfn_to_page(pte_pfn(x))
+#define pte_pfn(x)             ((unsigned long)((x).pte_high >> 6))
+
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+       pte_t pte;
+
+       pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f);
+       pte.pte_low = pgprot_val(prot);
+
+       return pte;
+}
+
+#else
 
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)             ((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
@@ -131,6 +143,8 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
 #endif
 #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) */
 
+#define pte_page(x)            pfn_to_page(pte_pfn(x))
+
 #define __pgd_offset(address)  pgd_index(address)
 #define __pud_offset(address)  (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
 #define __pmd_offset(address)  (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
@@ -166,7 +180,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
 
 #else
 
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_XPA)
 
 /* Swap entries must have VALID and GLOBAL bits cleared. */
 #define __swp_type(x)                  (((x).val >> 4) & 0x1f)
@@ -175,6 +189,15 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
 #define __pte_to_swp_entry(pte)                ((swp_entry_t) { (pte).pte_high })
 #define __swp_entry_to_pte(x)          ((pte_t) { 0, (x).val })
 
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+
+/* Swap entries must have VALID and GLOBAL bits cleared. */
+#define __swp_type(x)                  (((x).val >> 2) & 0x1f)
+#define __swp_offset(x)                         ((x).val >> 7)
+#define __swp_entry(type, offset)      ((swp_entry_t)  { ((type) << 2) | ((offset) << 7) })
+#define __pte_to_swp_entry(pte)                ((swp_entry_t) { (pte).pte_high })
+#define __swp_entry_to_pte(x)          ((pte_t) { 0, (x).val })
+
 #else
 /*
  * Constraints:
index cf661a2fb14113f9020c594b93bbfdc4404bceaa..514cbc0a6a6760fd84d77c3760aa9ce2ac682fd5 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/cachectl.h>
 #include <asm/fixmap.h>
 
-#ifdef CONFIG_PAGE_SIZE_64KB
+#if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48)
 #include <asm-generic/pgtable-nopmd.h>
 #else
 #include <asm-generic/pgtable-nopud.h>
 #define PTE_ORDER              0
 #endif
 #ifdef CONFIG_PAGE_SIZE_16KB
-#define PGD_ORDER              0
+#ifdef CONFIG_MIPS_VA_BITS_48
+#define PGD_ORDER               1
+#else
+#define PGD_ORDER               0
+#endif
 #define PUD_ORDER              aieeee_attempt_to_allocate_pud
 #define PMD_ORDER              0
 #define PTE_ORDER              0
 #ifdef CONFIG_PAGE_SIZE_64KB
 #define PGD_ORDER              0
 #define PUD_ORDER              aieeee_attempt_to_allocate_pud
+#ifdef CONFIG_MIPS_VA_BITS_48
+#define PMD_ORDER              0
+#else
 #define PMD_ORDER              aieeee_attempt_to_allocate_pmd
+#endif
 #define PTE_ORDER              0
 #endif
 
 #endif
 #define PTRS_PER_PTE   ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
 
-#if PGDIR_SIZE >= TASK_SIZE64
-#define USER_PTRS_PER_PGD      (1)
-#else
-#define USER_PTRS_PER_PGD      (TASK_SIZE64 / PGDIR_SIZE)
-#endif
+#define USER_PTRS_PER_PGD       ((TASK_SIZE64 / PGDIR_SIZE)?(TASK_SIZE64 / PGDIR_SIZE):1)
 #define FIRST_USER_ADDRESS     0UL
 
 /*
index 97b313882678084857129b811cea812a723c6a3a..f88a48cd68b2869049016c7d153ee2415e327848 100644 (file)
  * unpredictable things.  The code (when it is written) to deal with
  * this problem will be in the update_mmu_cache() code for the r4k.
  */
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_XPA)
 
 /*
- * The following bits are implemented by the TLB hardware
+ * Page table bit offsets used for 64 bit physical addressing on
+ * MIPS32r5 with XPA.
  */
-#define _PAGE_NO_EXEC_SHIFT    0
-#define _PAGE_NO_EXEC          (1 << _PAGE_NO_EXEC_SHIFT)
-#define _PAGE_NO_READ_SHIFT    (_PAGE_NO_EXEC_SHIFT + 1)
-#define _PAGE_NO_READ          (1 << _PAGE_NO_READ_SHIFT)
-#define _PAGE_GLOBAL_SHIFT     (_PAGE_NO_READ_SHIFT + 1)
-#define _PAGE_GLOBAL           (1 << _PAGE_GLOBAL_SHIFT)
-#define _PAGE_VALID_SHIFT      (_PAGE_GLOBAL_SHIFT + 1)
-#define _PAGE_VALID            (1 << _PAGE_VALID_SHIFT)
-#define _PAGE_DIRTY_SHIFT      (_PAGE_VALID_SHIFT + 1)
-#define _PAGE_DIRTY            (1 << _PAGE_DIRTY_SHIFT)
-#define _CACHE_SHIFT           (_PAGE_DIRTY_SHIFT + 1)
-#define _CACHE_MASK            (7 << _CACHE_SHIFT)
-
-/*
- * The following bits are implemented in software
- */
-#define _PAGE_PRESENT_SHIFT    (24)
-#define _PAGE_PRESENT          (1 << _PAGE_PRESENT_SHIFT)
-#define _PAGE_READ_SHIFT       (_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_READ             (1 << _PAGE_READ_SHIFT)
-#define _PAGE_WRITE_SHIFT      (_PAGE_READ_SHIFT + 1)
-#define _PAGE_WRITE            (1 << _PAGE_WRITE_SHIFT)
-#define _PAGE_ACCESSED_SHIFT   (_PAGE_WRITE_SHIFT + 1)
-#define _PAGE_ACCESSED         (1 << _PAGE_ACCESSED_SHIFT)
-#define _PAGE_MODIFIED_SHIFT   (_PAGE_ACCESSED_SHIFT + 1)
-#define _PAGE_MODIFIED         (1 << _PAGE_MODIFIED_SHIFT)
-
-#define _PFN_SHIFT             (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
+enum pgtable_bits {
+       /* Used by TLB hardware (placed in EntryLo*) */
+       _PAGE_NO_EXEC_SHIFT,
+       _PAGE_NO_READ_SHIFT,
+       _PAGE_GLOBAL_SHIFT,
+       _PAGE_VALID_SHIFT,
+       _PAGE_DIRTY_SHIFT,
+       _CACHE_SHIFT,
+
+       /* Used only by software (masked out before writing EntryLo*) */
+       _PAGE_PRESENT_SHIFT = 24,
+       _PAGE_WRITE_SHIFT,
+       _PAGE_ACCESSED_SHIFT,
+       _PAGE_MODIFIED_SHIFT,
+};
 
 /*
  * Bits for extended EntryLo0/EntryLo1 registers
  */
 #define _PFNX_MASK             0xffffff
 
-#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
 /*
- * The following bits are implemented in software
+ * Page table bit offsets used for 36 bit physical addressing on MIPS32,
+ * for example with Alchemy or Netlogic XLP/XLR.
  */
-#define _PAGE_PRESENT_SHIFT    (0)
-#define _PAGE_PRESENT          (1 << _PAGE_PRESENT_SHIFT)
-#define _PAGE_READ_SHIFT       (_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_READ             (1 << _PAGE_READ_SHIFT)
-#define _PAGE_WRITE_SHIFT      (_PAGE_READ_SHIFT + 1)
-#define _PAGE_WRITE            (1 << _PAGE_WRITE_SHIFT)
-#define _PAGE_ACCESSED_SHIFT   (_PAGE_WRITE_SHIFT + 1)
-#define _PAGE_ACCESSED         (1 << _PAGE_ACCESSED_SHIFT)
-#define _PAGE_MODIFIED_SHIFT   (_PAGE_ACCESSED_SHIFT + 1)
-#define _PAGE_MODIFIED         (1 << _PAGE_MODIFIED_SHIFT)
+enum pgtable_bits {
+       /* Used by TLB hardware (placed in EntryLo*) */
+       _PAGE_GLOBAL_SHIFT,
+       _PAGE_VALID_SHIFT,
+       _PAGE_DIRTY_SHIFT,
+       _CACHE_SHIFT,
+
+       /* Used only by software (masked out before writing EntryLo*) */
+       _PAGE_PRESENT_SHIFT = _CACHE_SHIFT + 3,
+       _PAGE_NO_READ_SHIFT,
+       _PAGE_WRITE_SHIFT,
+       _PAGE_ACCESSED_SHIFT,
+       _PAGE_MODIFIED_SHIFT,
+};
 
-/*
- * The following bits are implemented by the TLB hardware
- */
-#define _PAGE_GLOBAL_SHIFT     (_PAGE_MODIFIED_SHIFT + 4)
-#define _PAGE_GLOBAL           (1 << _PAGE_GLOBAL_SHIFT)
-#define _PAGE_VALID_SHIFT      (_PAGE_GLOBAL_SHIFT + 1)
-#define _PAGE_VALID            (1 << _PAGE_VALID_SHIFT)
-#define _PAGE_DIRTY_SHIFT      (_PAGE_VALID_SHIFT + 1)
-#define _PAGE_DIRTY            (1 << _PAGE_DIRTY_SHIFT)
-#define _CACHE_UNCACHED_SHIFT  (_PAGE_DIRTY_SHIFT + 1)
-#define _CACHE_UNCACHED                (1 << _CACHE_UNCACHED_SHIFT)
-#define _CACHE_MASK            _CACHE_UNCACHED
+#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
-#define _PFN_SHIFT             PAGE_SHIFT
+/* Page table bits used for r3k systems */
+enum pgtable_bits {
+       /* Used only by software (writes to EntryLo ignored) */
+       _PAGE_PRESENT_SHIFT,
+       _PAGE_NO_READ_SHIFT,
+       _PAGE_WRITE_SHIFT,
+       _PAGE_ACCESSED_SHIFT,
+       _PAGE_MODIFIED_SHIFT,
+
+       /* Used by TLB hardware (placed in EntryLo) */
+       _PAGE_GLOBAL_SHIFT = 8,
+       _PAGE_VALID_SHIFT,
+       _PAGE_DIRTY_SHIFT,
+       _CACHE_UNCACHED_SHIFT,
+};
 
 #else
-/*
- * Below are the "Normal" R4K cases
- */
 
-/*
- * The following bits are implemented in software
- */
-#define _PAGE_PRESENT_SHIFT    0
+/* Page table bits used for r4k systems */
+enum pgtable_bits {
+       /* Used only by software (masked out before writing EntryLo*) */
+       _PAGE_PRESENT_SHIFT,
+#if !defined(CONFIG_CPU_HAS_RIXI)
+       _PAGE_NO_READ_SHIFT,
+#endif
+       _PAGE_WRITE_SHIFT,
+       _PAGE_ACCESSED_SHIFT,
+       _PAGE_MODIFIED_SHIFT,
+#if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
+       _PAGE_HUGE_SHIFT,
+#endif
+
+       /* Used by TLB hardware (placed in EntryLo*) */
+#if defined(CONFIG_CPU_HAS_RIXI)
+       _PAGE_NO_EXEC_SHIFT,
+       _PAGE_NO_READ_SHIFT,
+#endif
+       _PAGE_GLOBAL_SHIFT,
+       _PAGE_VALID_SHIFT,
+       _PAGE_DIRTY_SHIFT,
+       _CACHE_SHIFT,
+};
+
+#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */
+
+/* Used only by software */
 #define _PAGE_PRESENT          (1 << _PAGE_PRESENT_SHIFT)
-/* R2 or later cores check for RI/XI support to determine _PAGE_READ */
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
-#define _PAGE_WRITE_SHIFT      (_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_WRITE            (1 << _PAGE_WRITE_SHIFT)
-#else
-#define _PAGE_READ_SHIFT       (_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_READ             (1 << _PAGE_READ_SHIFT)
-#define _PAGE_WRITE_SHIFT      (_PAGE_READ_SHIFT + 1)
 #define _PAGE_WRITE            (1 << _PAGE_WRITE_SHIFT)
-#endif
-#define _PAGE_ACCESSED_SHIFT   (_PAGE_WRITE_SHIFT + 1)
 #define _PAGE_ACCESSED         (1 << _PAGE_ACCESSED_SHIFT)
-#define _PAGE_MODIFIED_SHIFT   (_PAGE_ACCESSED_SHIFT + 1)
 #define _PAGE_MODIFIED         (1 << _PAGE_MODIFIED_SHIFT)
-
 #if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
-/* Huge TLB page */
-#define _PAGE_HUGE_SHIFT       (_PAGE_MODIFIED_SHIFT + 1)
-#define _PAGE_HUGE             (1 << _PAGE_HUGE_SHIFT)
-#endif /* CONFIG_64BIT && CONFIG_MIPS_HUGE_TLB_SUPPORT */
-
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
-/* XI - page cannot be executed */
-#ifdef _PAGE_HUGE_SHIFT
-#define _PAGE_NO_EXEC_SHIFT    (_PAGE_HUGE_SHIFT + 1)
-#else
-#define _PAGE_NO_EXEC_SHIFT    (_PAGE_MODIFIED_SHIFT + 1)
+# define _PAGE_HUGE            (1 << _PAGE_HUGE_SHIFT)
 #endif
-#define _PAGE_NO_EXEC          (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0)
-
-/* RI - page cannot be read */
-#define _PAGE_READ_SHIFT       (_PAGE_NO_EXEC_SHIFT + 1)
-#define _PAGE_READ             (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT))
-#define _PAGE_NO_READ_SHIFT    _PAGE_READ_SHIFT
-#define _PAGE_NO_READ          (cpu_has_rixi ? (1 << _PAGE_READ_SHIFT) : 0)
-#endif /* defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) */
-
-#if defined(_PAGE_NO_READ_SHIFT)
-#define _PAGE_GLOBAL_SHIFT     (_PAGE_NO_READ_SHIFT + 1)
-#elif defined(_PAGE_HUGE_SHIFT)
-#define _PAGE_GLOBAL_SHIFT     (_PAGE_HUGE_SHIFT + 1)
-#else
-#define _PAGE_GLOBAL_SHIFT     (_PAGE_MODIFIED_SHIFT + 1)
+
+/* Used by TLB hardware (placed in EntryLo*) */
+#if defined(CONFIG_XPA)
+# define _PAGE_NO_EXEC         (1 << _PAGE_NO_EXEC_SHIFT)
+#elif defined(CONFIG_CPU_HAS_RIXI)
+# define _PAGE_NO_EXEC         (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0)
 #endif
+#define _PAGE_NO_READ          (1 << _PAGE_NO_READ_SHIFT)
 #define _PAGE_GLOBAL           (1 << _PAGE_GLOBAL_SHIFT)
-
-#define _PAGE_VALID_SHIFT      (_PAGE_GLOBAL_SHIFT + 1)
 #define _PAGE_VALID            (1 << _PAGE_VALID_SHIFT)
-#define _PAGE_DIRTY_SHIFT      (_PAGE_VALID_SHIFT + 1)
 #define _PAGE_DIRTY            (1 << _PAGE_DIRTY_SHIFT)
-#define _CACHE_SHIFT           (_PAGE_DIRTY_SHIFT + 1)
-#define _CACHE_MASK            (7 << _CACHE_SHIFT)
-
-#define _PFN_SHIFT             (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
-
-#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+# define _CACHE_UNCACHED       (1 << _CACHE_UNCACHED_SHIFT)
+# define _CACHE_MASK           _CACHE_UNCACHED
+# define _PFN_SHIFT            PAGE_SHIFT
+#else
+# define _CACHE_MASK           (7 << _CACHE_SHIFT)
+# define _PFN_SHIFT            (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
+#endif
 
 #ifndef _PAGE_NO_EXEC
 #define _PAGE_NO_EXEC          0
 #endif
-#ifndef _PAGE_NO_READ
-#define _PAGE_NO_READ          0
-#endif
 
 #define _PAGE_SILENT_READ      _PAGE_VALID
 #define _PAGE_SILENT_WRITE     _PAGE_DIRTY
  */
 
 
-#ifndef __ASSEMBLY__
 /*
  * pte_to_entrylo converts a page table entry (PTE) into a Mips
  * entrylo0/1 value.
  */
 static inline uint64_t pte_to_entrylo(unsigned long pte_val)
 {
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
+#ifdef CONFIG_CPU_HAS_RIXI
        if (cpu_has_rixi) {
                int sa;
 #ifdef CONFIG_32BIT
@@ -218,7 +200,6 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
 
        return pte_val >> _PAGE_GLOBAL_SHIFT;
 }
-#endif
 
 /*
  * Cache attributes
@@ -274,7 +255,7 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
 #define _CACHE_UNCACHED_ACCELERATED    (7<<_CACHE_SHIFT)
 #endif
 
-#define __READABLE     (_PAGE_SILENT_READ | _PAGE_READ | _PAGE_ACCESSED)
+#define __READABLE     (_PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE    (_PAGE_SILENT_WRITE | _PAGE_WRITE | _PAGE_MODIFIED)
 
 #define _PAGE_CHG_MASK (_PAGE_ACCESSED | _PAGE_MODIFIED |      \
index 9a4fe0133ff1c7d82685d426dc1a91b371a972a6..e07a105cafc26fca81d3f1d1fb80d91201a40559 100644 (file)
 struct mm_struct;
 struct vm_area_struct;
 
-#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
-#define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | \
+#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_NO_READ | \
+                                _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_WRITE | \
                                 _page_cachable_default)
-#define PAGE_COPY      __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_NO_EXEC | \
+#define PAGE_COPY      __pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | \
                                 _page_cachable_default)
-#define PAGE_READONLY  __pgprot(_PAGE_PRESENT | _PAGE_READ | \
+#define PAGE_READONLY  __pgprot(_PAGE_PRESENT | \
                                 _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 | _PAGE_READ | _PAGE_WRITE | \
+#define PAGE_USERIO    __pgprot(_PAGE_PRESENT | _PAGE_WRITE | \
                                 _page_cachable_default)
 #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \
                        __WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED)
@@ -127,10 +128,19 @@ do {                                                                      \
        }                                                               \
 } while(0)
 
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pteval);
+
 #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
-#define pte_none(pte)          (!(((pte).pte_high) & ~_PAGE_GLOBAL))
+#ifdef CONFIG_XPA
+# define pte_none(pte)         (!(((pte).pte_high) & ~_PAGE_GLOBAL))
+#else
+# define pte_none(pte)         (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
+#endif
+
 #define pte_present(pte)       ((pte).pte_low & _PAGE_PRESENT)
+#define pte_no_exec(pte)       ((pte).pte_low & _PAGE_NO_EXEC)
 
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
@@ -138,17 +148,23 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
        smp_wmb();
        ptep->pte_low = pte.pte_low;
 
+#ifdef CONFIG_XPA
        if (pte.pte_high & _PAGE_GLOBAL) {
+#else
+       if (pte.pte_low & _PAGE_GLOBAL) {
+#endif
                pte_t *buddy = ptep_buddy(ptep);
                /*
                 * Make sure the buddy is global too (if it's !none,
                 * it better already be global)
                 */
-               if (pte_none(*buddy))
+               if (pte_none(*buddy)) {
+                       if (!config_enabled(CONFIG_XPA))
+                               buddy->pte_low |= _PAGE_GLOBAL;
                        buddy->pte_high |= _PAGE_GLOBAL;
+               }
        }
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -156,8 +172,13 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
 
        htw_stop();
        /* Preserve global status for the pair */
-       if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL)
-               null.pte_high = _PAGE_GLOBAL;
+       if (config_enabled(CONFIG_XPA)) {
+               if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL)
+                       null.pte_high = _PAGE_GLOBAL;
+       } else {
+               if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
+                       null.pte_low = null.pte_high = _PAGE_GLOBAL;
+       }
 
        set_pte_at(mm, addr, ptep, null);
        htw_start();
@@ -166,6 +187,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
 
 #define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
+#define pte_no_exec(pte)       (pte_val(pte) & _PAGE_NO_EXEC)
 
 /*
  * Certain architectures need to do special things when pte's
@@ -187,30 +209,42 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                 * For SMP, multiple CPUs can race, so we need to do
                 * this atomically.
                 */
-#ifdef CONFIG_64BIT
-#define LL_INSN "lld"
-#define SC_INSN "scd"
-#else /* CONFIG_32BIT */
-#define LL_INSN "ll"
-#define SC_INSN "sc"
-#endif
                unsigned long page_global = _PAGE_GLOBAL;
                unsigned long tmp;
 
-               __asm__ __volatile__ (
-                       "       .set    push\n"
-                       "       .set    noreorder\n"
-                       "1:     " LL_INSN "     %[tmp], %[buddy]\n"
-                       "       bnez    %[tmp], 2f\n"
-                       "        or     %[tmp], %[tmp], %[global]\n"
-                       "       " SC_INSN "     %[tmp], %[buddy]\n"
-                       "       beqz    %[tmp], 1b\n"
-                       "        nop\n"
-                       "2:\n"
-                       "       .set pop"
-                       : [buddy] "+m" (buddy->pte),
-                         [tmp] "=&r" (tmp)
+               if (kernel_uses_llsc && R10000_LLSC_WAR) {
+                       __asm__ __volatile__ (
+                       "       .set    arch=r4000                      \n"
+                       "       .set    push                            \n"
+                       "       .set    noreorder                       \n"
+                       "1:"    __LL    "%[tmp], %[buddy]               \n"
+                       "       bnez    %[tmp], 2f                      \n"
+                       "        or     %[tmp], %[tmp], %[global]       \n"
+                               __SC    "%[tmp], %[buddy]               \n"
+                       "       beqzl   %[tmp], 1b                      \n"
+                       "       nop                                     \n"
+                       "2:                                             \n"
+                       "       .set    pop                             \n"
+                       "       .set    mips0                           \n"
+                       : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
+                       : [global] "r" (page_global));
+               } else if (kernel_uses_llsc) {
+                       __asm__ __volatile__ (
+                       "       .set    "MIPS_ISA_ARCH_LEVEL"           \n"
+                       "       .set    push                            \n"
+                       "       .set    noreorder                       \n"
+                       "1:"    __LL    "%[tmp], %[buddy]               \n"
+                       "       bnez    %[tmp], 2f                      \n"
+                       "        or     %[tmp], %[tmp], %[global]       \n"
+                               __SC    "%[tmp], %[buddy]               \n"
+                       "       beqz    %[tmp], 1b                      \n"
+                       "       nop                                     \n"
+                       "2:                                             \n"
+                       "       .set    pop                             \n"
+                       "       .set    mips0                           \n"
+                       : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
                        : [global] "r" (page_global));
+               }
 #else /* !CONFIG_SMP */
                if (pte_none(*buddy))
                        pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
@@ -218,7 +252,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
        }
 #endif
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -234,6 +267,22 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
 }
 #endif
 
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pteval)
+{
+       extern void __update_cache(unsigned long address, pte_t pte);
+
+       if (!pte_present(pteval))
+               goto cache_sync_done;
+
+       if (pte_present(*ptep) && (pte_pfn(*ptep) == pte_pfn(pteval)))
+               goto cache_sync_done;
+
+       __update_cache(addr, pteval);
+cache_sync_done:
+       set_pte(ptep, pteval);
+}
+
 /*
  * (pmds are folded into puds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
@@ -270,6 +319,8 @@ static inline int pte_young(pte_t pte)      { return pte.pte_low & _PAGE_ACCESSED; }
 static inline pte_t pte_wrprotect(pte_t pte)
 {
        pte.pte_low  &= ~_PAGE_WRITE;
+       if (!config_enabled(CONFIG_XPA))
+               pte.pte_low &= ~_PAGE_SILENT_WRITE;
        pte.pte_high &= ~_PAGE_SILENT_WRITE;
        return pte;
 }
@@ -277,6 +328,8 @@ static inline pte_t pte_wrprotect(pte_t pte)
 static inline pte_t pte_mkclean(pte_t pte)
 {
        pte.pte_low  &= ~_PAGE_MODIFIED;
+       if (!config_enabled(CONFIG_XPA))
+               pte.pte_low &= ~_PAGE_SILENT_WRITE;
        pte.pte_high &= ~_PAGE_SILENT_WRITE;
        return pte;
 }
@@ -284,6 +337,8 @@ static inline pte_t pte_mkclean(pte_t pte)
 static inline pte_t pte_mkold(pte_t pte)
 {
        pte.pte_low  &= ~_PAGE_ACCESSED;
+       if (!config_enabled(CONFIG_XPA))
+               pte.pte_low &= ~_PAGE_SILENT_READ;
        pte.pte_high &= ~_PAGE_SILENT_READ;
        return pte;
 }
@@ -291,24 +346,33 @@ static inline pte_t pte_mkold(pte_t pte)
 static inline pte_t pte_mkwrite(pte_t pte)
 {
        pte.pte_low |= _PAGE_WRITE;
-       if (pte.pte_low & _PAGE_MODIFIED)
+       if (pte.pte_low & _PAGE_MODIFIED) {
+               if (!config_enabled(CONFIG_XPA))
+                       pte.pte_low |= _PAGE_SILENT_WRITE;
                pte.pte_high |= _PAGE_SILENT_WRITE;
+       }
        return pte;
 }
 
 static inline pte_t pte_mkdirty(pte_t pte)
 {
        pte.pte_low |= _PAGE_MODIFIED;
-       if (pte.pte_low & _PAGE_WRITE)
+       if (pte.pte_low & _PAGE_WRITE) {
+               if (!config_enabled(CONFIG_XPA))
+                       pte.pte_low |= _PAGE_SILENT_WRITE;
                pte.pte_high |= _PAGE_SILENT_WRITE;
+       }
        return pte;
 }
 
 static inline pte_t pte_mkyoung(pte_t pte)
 {
        pte.pte_low |= _PAGE_ACCESSED;
-       if (pte.pte_low & _PAGE_READ)
+       if (!(pte.pte_low & _PAGE_NO_READ)) {
+               if (!config_enabled(CONFIG_XPA))
+                       pte.pte_low |= _PAGE_SILENT_READ;
                pte.pte_high |= _PAGE_SILENT_READ;
+       }
        return pte;
 }
 #else
@@ -353,13 +417,8 @@ static inline pte_t pte_mkdirty(pte_t pte)
 static inline pte_t pte_mkyoung(pte_t pte)
 {
        pte_val(pte) |= _PAGE_ACCESSED;
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        if (!(pte_val(pte) & _PAGE_NO_READ))
                pte_val(pte) |= _PAGE_SILENT_READ;
-       else
-#endif
-       if (pte_val(pte) & _PAGE_READ)
-               pte_val(pte) |= _PAGE_SILENT_READ;
        return pte;
 }
 
@@ -411,7 +470,7 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
  */
 #define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
 
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_XPA)
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
        pte.pte_low  &= (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK);
@@ -420,6 +479,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
        pte.pte_high |= pgprot_val(newprot) & ~_PFN_MASK;
        return pte;
 }
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+       pte.pte_low  &= _PAGE_CHG_MASK;
+       pte.pte_high &= (_PFN_MASK | _CACHE_MASK);
+       pte.pte_low  |= pgprot_val(newprot);
+       pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK);
+       return pte;
+}
 #else
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
@@ -430,15 +498,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
        pte_t pte);
-extern void __update_cache(struct vm_area_struct *vma, unsigned long address,
-       pte_t pte);
 
 static inline void update_mmu_cache(struct vm_area_struct *vma,
        unsigned long address, pte_t *ptep)
 {
        pte_t pte = *ptep;
        __update_tlb(vma, address, pte);
-       __update_cache(vma, address, pte);
 }
 
 static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
@@ -542,13 +607,8 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
 {
        pmd_val(pmd) |= _PAGE_ACCESSED;
 
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        if (!(pmd_val(pmd) & _PAGE_NO_READ))
                pmd_val(pmd) |= _PAGE_SILENT_READ;
-       else
-#endif
-       if (pmd_val(pmd) & _PAGE_READ)
-               pmd_val(pmd) |= _PAGE_SILENT_READ;
 
        return pmd;
 }
index 041153f5cf93432ea1140c10cd53c3d48e91ab76..7e78b6208d7d140a6a76a4e4f0a51486cd18191e 100644 (file)
@@ -63,7 +63,11 @@ extern unsigned int vced_count, vcei_count;
  * 8192EB ...
  */
 #define TASK_SIZE32    0x7fff8000UL
-#define TASK_SIZE64    0x10000000000UL
+#ifdef CONFIG_MIPS_VA_BITS_48
+#define TASK_SIZE64     (0x1UL << ((cpu_data[0].vmbits>48)?48:cpu_data[0].vmbits))
+#else
+#define TASK_SIZE64     0x10000000000UL
+#endif
 #define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
 #define STACK_TOP_MAX  TASK_SIZE64
 
@@ -355,6 +359,10 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
  */
 extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
 
+static inline void flush_thread(void)
+{
+}
+
 unsigned long get_wchan(struct task_struct *p);
 
 #define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \
index 1d8a2e2c75c1f5f933b5618903565cdfcb308064..684fb3a12ed364549fb4fdfe81b75f2ebccd7ecf 100644 (file)
@@ -2,27 +2,32 @@
 
 #include <linux/unistd.h>
 
-/*
- * Kludge alert:
- *
- * The generic seccomp code currently allows only a single compat ABI. Until
- * this is fixed we priorize O32 as the compat ABI over N32.
- */
-#ifdef CONFIG_MIPS32_O32
-
-#define __NR_seccomp_read_32           4003
-#define __NR_seccomp_write_32          4004
-#define __NR_seccomp_exit_32           4001
-#define __NR_seccomp_sigreturn_32      4193    /* rt_sigreturn */
-
-#elif defined(CONFIG_MIPS32_N32)
-
-#define __NR_seccomp_read_32           6000
-#define __NR_seccomp_write_32          6001
-#define __NR_seccomp_exit_32           6058
-#define __NR_seccomp_sigreturn_32      6211    /* rt_sigreturn */
-
-#endif /* CONFIG_MIPS32_O32 */
+#ifdef CONFIG_COMPAT
+static inline const int *get_compat_mode1_syscalls(void)
+{
+       static const int syscalls_O32[] = {
+               __NR_O32_Linux + 3, __NR_O32_Linux + 4,
+               __NR_O32_Linux + 1, __NR_O32_Linux + 193,
+               0, /* null terminated */
+       };
+       static const int syscalls_N32[] = {
+               __NR_N32_Linux + 0, __NR_N32_Linux + 1,
+               __NR_N32_Linux + 58, __NR_N32_Linux + 211,
+               0, /* null terminated */
+       };
+
+       if (config_enabled(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS))
+               return syscalls_O32;
+
+       if (config_enabled(CONFIG_MIPS32_N32))
+               return syscalls_N32;
+
+       BUG();
+}
+
+#define get_compat_mode1_syscalls get_compat_mode1_syscalls
+
+#endif /* CONFIG_COMPAT */
 
 #include <asm-generic/seccomp.h>
 
index ec0dacf6f0cb58616612155f160b9eede2d6d0ca..32a84837b8fadf500e523b87d7796a5b5ae7452d 100644 (file)
                                        (cpu)*BCM1480_IMR_ALIAS_MAILBOX_SPACING)
 #define A_BCM1480_IMR_ALIAS_MAILBOX_REGISTER(cpu, reg) (A_BCM1480_IMR_ALIAS_MAILBOX(cpu)+(reg))
 
-#define R_BCM1480_IMR_ALIAS_MAILBOX_0          0x0000          /* 0x0x0 */
-#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET      0x0008          /* 0x0x8 */
+#define R_BCM1480_IMR_ALIAS_MAILBOX_0          0x0000
+#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET      0x0008
 
 /*
  * these macros work together to build the address of a mailbox
index 003e273eff4cef853b27a6b348be4d87de882774..2292373ff11ad40ab5de5e448a84a2764e2ec957 100644 (file)
 
 #include <uapi/asm/signal.h>
 
+#ifdef CONFIG_MIPS32_COMPAT
+extern struct mips_abi mips_abi_32;
 
-#ifdef CONFIG_TRAD_SIGNALS
-#define sig_uses_siginfo(ka)   ((ka)->sa.sa_flags & SA_SIGINFO)
+#define sig_uses_siginfo(ka, abi)                               \
+       ((abi != &mips_abi_32) ? 1 :                            \
+               ((ka)->sa.sa_flags & SA_SIGINFO))
 #else
-#define sig_uses_siginfo(ka)   (1)
+#define sig_uses_siginfo(ka, abi)                               \
+       (config_enabled(CONFIG_64BIT) ? 1 :                     \
+               (config_enabled(CONFIG_TRAD_SIGNALS) ?          \
+                       ((ka)->sa.sa_flags & SA_SIGINFO) : 1) )
 #endif
 
 #include <asm/sigcontext.h>
index 326c16ebd589949425e0675bd3906377de5723e3..2ae1f61a4a95600e1986df03687fb478fc668966 100644 (file)
@@ -29,7 +29,7 @@ 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 void mips_cps_boot_vpes(struct core_boot_config *cfg, unsigned vpe);
 
 extern void mips_cps_pm_save(void);
 extern void mips_cps_pm_restore(void);
index 28b5d84a5022a13c7b9c782ad446c30bdff06b29..ebb5c0f2f90daef7b2bcca348fb90df2b7530037 100644 (file)
@@ -105,7 +105,7 @@ do {                                                                        \
        __clear_software_ll_bit();                                      \
        if (cpu_has_userlocal)                                          \
                write_c0_userlocal(task_thread_info(next)->tp_value);   \
-       __restore_watch();                                              \
+       __restore_watch(next);                                          \
        (last) = resume(prev, next, task_thread_info(next));            \
 } while (0)
 
index fc1cdd25fcda3fa7b632b23039a3b810ef47d322..b6ecfeee4dbe8aca256803ee2f980575825133e8 100644 (file)
@@ -171,7 +171,8 @@ Ip_u2u1(_wsbh);
 Ip_u3u1u2(_xor);
 Ip_u2u1u3(_xori);
 Ip_u2u1(_yield);
-
+Ip_u1u2(_ldpte);
+Ip_u2u1u3(_lddir);
 
 /* Handle labels. */
 struct uasm_label {
index 20126ec793596a6ab2ab2a2e35d6e96e9ac59541..6ffe3eadf105cb226c269511121be7e3ff349507 100644 (file)
 
 #include <asm/mipsregs.h>
 
-void mips_install_watch_registers(void);
+void mips_install_watch_registers(struct task_struct *t);
 void mips_read_watch_registers(void);
 void mips_clear_watch_registers(void);
 void mips_probe_watch_registers(struct cpuinfo_mips *c);
 
 #ifdef CONFIG_HARDWARE_WATCHPOINTS
-#define __restore_watch() do {                                         \
+#define __restore_watch(task) do {                                     \
        if (unlikely(test_bit(TIF_LOAD_WATCH,                           \
-                             &current_thread_info()->flags))) {        \
-               mips_install_watch_registers();                         \
+                             &task_thread_info(task)->flags))) {       \
+               mips_install_watch_registers(task);                     \
        }                                                               \
 } while (0)
 
 #else
-#define __restore_watch() do {} while (0)
+#define __restore_watch(task) do {} while (0)
 #endif
 
 #endif /* _ASM_WATCH_H */
index ddea53e3a9bb7bbd56463a0727ff2b3bc378f614..8051f9aa13796f5e6f63a249883b362072c99217 100644 (file)
@@ -167,6 +167,7 @@ enum cop1_sdw_func {
        fceill_op    =  0x0a, ffloorl_op   =  0x0b,
        fround_op    =  0x0c, ftrunc_op    =  0x0d,
        fceil_op     =  0x0e, ffloor_op    =  0x0f,
+       fsel_op      =  0x10,
        fmovc_op     =  0x11, fmovz_op     =  0x12,
        fmovn_op     =  0x13, fseleqz_op   =  0x14,
        frecip_op    =  0x15, frsqrt_op    =  0x16,
@@ -203,6 +204,16 @@ enum mad_func {
        nmadd_fp_op     = 0x0c, nmsub_fp_op     = 0x0e
 };
 
+/*
+ * func field for page table walker (Loongson-3).
+ */
+enum ptw_func {
+       lwdir_op = 0x00,
+       lwpte_op = 0x01,
+       lddir_op = 0x02,
+       ldpte_op = 0x03,
+};
+
 /*
  * func field for special3 lx opcodes (Cavium Octeon).
  */
index cc49dc240d67183f0cedb5408892ea9fdb645891..8069cf766603ea3e2e5f090bab3e6547a7ac46b6 100644 (file)
@@ -28,7 +28,7 @@
 
 #define __ARCH_SIGSYS
 
-#include <uapi/asm-generic/siginfo.h>
+#include <asm-generic/siginfo.h>
 
 /* We can't use generic siginfo_t, because our si_code and si_errno are swapped */
 typedef struct siginfo {
@@ -42,13 +42,13 @@ typedef struct siginfo {
 
                /* kill() */
                struct {
-                       pid_t _pid;             /* sender's pid */
+                       __kernel_pid_t _pid;    /* sender's pid */
                        __ARCH_SI_UID_T _uid;   /* sender's uid */
                } _kill;
 
                /* POSIX.1b timers */
                struct {
-                       timer_t _tid;           /* timer id */
+                       __kernel_timer_t _tid;  /* timer id */
                        int _overrun;           /* overrun count */
                        char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
                        sigval_t _sigval;       /* same as below */
@@ -57,26 +57,26 @@ typedef struct siginfo {
 
                /* POSIX.1b signals */
                struct {
-                       pid_t _pid;             /* sender's pid */
+                       __kernel_pid_t _pid;    /* sender's pid */
                        __ARCH_SI_UID_T _uid;   /* sender's uid */
                        sigval_t _sigval;
                } _rt;
 
                /* SIGCHLD */
                struct {
-                       pid_t _pid;             /* which child */
+                       __kernel_pid_t _pid;    /* which child */
                        __ARCH_SI_UID_T _uid;   /* sender's uid */
                        int _status;            /* exit code */
-                       clock_t _utime;
-                       clock_t _stime;
+                       __kernel_clock_t _utime;
+                       __kernel_clock_t _stime;
                } _sigchld;
 
                /* IRIX SIGCHLD */
                struct {
-                       pid_t _pid;             /* which child */
-                       clock_t _utime;
+                       __kernel_pid_t _pid;    /* which child */
+                       __kernel_clock_t _utime;
                        int _status;            /* exit code */
-                       clock_t _stime;
+                       __kernel_clock_t _stime;
                } _irix_sigchld;
 
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -123,6 +123,4 @@ typedef struct siginfo {
 #define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */
 #define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */
 
-#include <asm-generic/siginfo.h>
-
 #endif /* _UAPI_ASM_SIGINFO_H */
index 934b15b5b575f15b04fae0bf44065440773f7593..4e3f9b7a02e4997101843a9283c45cb97fa81866 100644 (file)
@@ -39,8 +39,6 @@
 
 #include "clock.h"
 
-static bool is_avt2;
-
 /* GPIOs */
 #define QI_LB60_GPIO_SD_CD             JZ_GPIO_PORTD(0)
 #define QI_LB60_GPIO_SD_VCC_EN_N       JZ_GPIO_PORTD(2)
@@ -367,43 +365,12 @@ static struct jz4740_mmc_platform_data qi_lb60_mmc_pdata = {
        .power_active_low       = 1,
 };
 
-/* OHCI */
-static struct regulator_consumer_supply avt2_usb_regulator_consumer =
-       REGULATOR_SUPPLY("vbus", "jz4740-ohci");
-
-static struct regulator_init_data avt2_usb_regulator_init_data = {
-       .num_consumer_supplies = 1,
-       .consumer_supplies = &avt2_usb_regulator_consumer,
-       .constraints = {
-               .name = "USB power",
-               .min_uV = 5000000,
-               .max_uV = 5000000,
-               .valid_modes_mask = REGULATOR_MODE_NORMAL,
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
-       },
-};
-
-static struct fixed_voltage_config avt2_usb_regulator_data = {
-       .supply_name = "USB power",
-       .microvolts = 5000000,
-       .gpio = JZ_GPIO_PORTB(17),
-       .init_data = &avt2_usb_regulator_init_data,
-};
-
-static struct platform_device avt2_usb_regulator_device = {
-       .name = "reg-fixed-voltage",
-       .id = -1,
-       .dev = {
-               .platform_data = &avt2_usb_regulator_data,
-       }
-};
-
+/* beeper */
 static struct pwm_lookup qi_lb60_pwm_lookup[] = {
        PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0,
                   PWM_POLARITY_NORMAL),
 };
 
-/* beeper */
 static struct platform_device qi_lb60_pwm_beeper = {
        .name = "pwm-beeper",
        .id = -1,
@@ -487,11 +454,6 @@ static int __init qi_lb60_init_platform_devices(void)
        spi_register_board_info(qi_lb60_spi_board_info,
                                ARRAY_SIZE(qi_lb60_spi_board_info));
 
-       if (is_avt2) {
-               platform_device_register(&avt2_usb_regulator_device);
-               platform_device_register(&jz4740_usb_ohci_device);
-       }
-
        pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup));
 
        return platform_add_devices(jz_platform_devices,
@@ -499,19 +461,9 @@ static int __init qi_lb60_init_platform_devices(void)
 
 }
 
-static __init int board_avt2(char *str)
-{
-       qi_lb60_mmc_pdata.card_detect_active_low = 1;
-       is_avt2 = true;
-
-       return 1;
-}
-__setup("avt2", board_avt2);
-
 static int __init qi_lb60_board_setup(void)
 {
-       printk(KERN_INFO "Qi Hardware JZ4740 QI %s setup\n",
-               is_avt2 ? "AVT2" : "LB60");
+       printk(KERN_INFO "Qi Hardware JZ4740 QI LB60 setup\n");
 
        board_gpio_setup();
 
index e8a463b9b663edec81ebe547aebbe8b7645a6adf..2f1dab35c061831263073707d6ee6e4c07816c4f 100644 (file)
 
 #include "clock.h"
 
-/* OHCI controller */
-static struct resource jz4740_usb_ohci_resources[] = {
-       {
-               .start  = JZ4740_UHC_BASE_ADDR,
-               .end    = JZ4740_UHC_BASE_ADDR + 0x1000 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = JZ4740_IRQ_UHC,
-               .end    = JZ4740_IRQ_UHC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device jz4740_usb_ohci_device = {
-       .name           = "jz4740-ohci",
-       .id             = -1,
-       .dev = {
-               .dma_mask = &jz4740_usb_ohci_device.dev.coherent_dma_mask,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-       },
-       .num_resources  = ARRAY_SIZE(jz4740_usb_ohci_resources),
-       .resource       = jz4740_usb_ohci_resources,
-};
-
 /* USB Device Controller */
 struct platform_device jz4740_udc_xceiv_device = {
        .name = "usb_phy_generic",
index b0988fd62fcc3e6b6b296d3647cd9cdea39043f1..e6053d07072fb61c782e6e5700b32a9dff619567 100644 (file)
@@ -44,7 +44,7 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON)       += r4k_fpu.o octeon_switch.o
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_SMP_UP)           += smp-up.o
-obj-$(CONFIG_CPU_BMIPS)                += smp-bmips.o bmips_vec.o
+obj-$(CONFIG_CPU_BMIPS)                += smp-bmips.o bmips_vec.o bmips_5xxx_init.o
 
 obj-$(CONFIG_MIPS_MT)          += mips-mt.o
 obj-$(CONFIG_MIPS_MT_FPAFF)    += mips-mt-fpaff.o
@@ -83,6 +83,8 @@ obj-$(CONFIG_I8253)           += i8253.o
 
 obj-$(CONFIG_GPIO_TXX9)                += gpio_txx9.o
 
+obj-$(CONFIG_RELOCATABLE)      += relocate.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
index 154e2039ea5ef13fe9ba8935eb01475031283913..1ea973b2abb1e0365db6ee4b867d3e32d355953c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/kbuild.h>
 #include <linux/suspend.h>
+#include <asm/cpu-info.h>
 #include <asm/pm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -338,6 +339,15 @@ void output_pm_defines(void)
 }
 #endif
 
+void output_cpuinfo_defines(void)
+{
+       COMMENT(" MIPS cpuinfo offsets. ");
+       DEFINE(CPUINFO_SIZE, sizeof(struct cpuinfo_mips));
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       OFFSET(CPUINFO_ASID_MASK, cpuinfo_mips, asid_mask);
+#endif
+}
+
 void output_kvm_defines(void)
 {
        COMMENT(" KVM/MIPS Specfic offsets. ");
index 1b992c6e3d8e212420673fbb697edeff0b6314e3..58ad63d7eb42413ee1259582fd6b666f699faa99 100644 (file)
@@ -30,21 +30,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(hdr)                                            \
-({                                                                     \
-       int __res = 1;                                                  \
-       struct elfhdr *__h = (hdr);                                     \
-                                                                       \
-       if (!mips_elf_check_machine(__h))                               \
-               __res = 0;                                              \
-       if (__h->e_ident[EI_CLASS] != ELFCLASS32)                       \
-               __res = 0;                                              \
-       if (((__h->e_flags & EF_MIPS_ABI2) == 0) ||                     \
-           ((__h->e_flags & EF_MIPS_ABI) != 0))                        \
-               __res = 0;                                              \
-                                                                       \
-       __res;                                                          \
-})
+#define elf_check_arch elfn32_check_arch
 
 #define TASK32_SIZE            0x7fff8000UL
 #undef ELF_ET_DYN_BASE
index abd3affe5fb3bd71367b908f9439b54ddea7a61c..49fb881481f7b6940dfb353dedeb412d2be584bb 100644 (file)
@@ -27,40 +27,10 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 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)                                            \
-({                                                                     \
-       int __res = 1;                                                  \
-       struct elfhdr *__h = (hdr);                                     \
-                                                                       \
-       if (!mips_elf_check_machine(__h))                               \
-               __res = 0;                                              \
-       if (__h->e_ident[EI_CLASS] != ELFCLASS32)                       \
-               __res = 0;                                              \
-       if ((__h->e_flags & EF_MIPS_ABI2) != 0)                         \
-               __res = 0;                                              \
-       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;                                                          \
-})
+#define elf_check_arch elfo32_check_arch
 
 #ifdef CONFIG_KVM_GUEST
 #define TASK32_SIZE            0x3fff8000UL
diff --git a/arch/mips/kernel/bmips_5xxx_init.S b/arch/mips/kernel/bmips_5xxx_init.S
new file mode 100644 (file)
index 0000000..adaa82e
--- /dev/null
@@ -0,0 +1,753 @@
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2011-2012 by Broadcom Corporation
+ *
+ * Init for bmips 5000.
+ * Used to init second core in dual core 5000's.
+ */
+
+#include <linux/init.h>
+
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheops.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+#include <asm/hazards.h>
+#include <asm/bmips.h>
+
+#ifdef CONFIG_CPU_BMIPS5000
+
+
+#define cacheop(kva, size, linesize, op)       \
+       .set noreorder                  ;       \
+       addu            t1, kva, size   ;       \
+       subu            t2, linesize, 1 ;       \
+       not             t2              ;       \
+       and             t0, kva, t2     ;       \
+       addiu           t1, t1, -1      ;       \
+       and             t1, t2          ;       \
+9:     cache           op, 0(t0)       ;       \
+       bne             t0, t1, 9b      ;       \
+        addu           t0, linesize    ;       \
+       .set reorder                    ;
+
+
+
+#define        IS_SHIFT        22
+#define        IL_SHIFT        19
+#define        IA_SHIFT        16
+#define        DS_SHIFT        13
+#define        DL_SHIFT        10
+#define        DA_SHIFT         7
+#define        IS_MASK          7
+#define        IL_MASK          7
+#define        IA_MASK          7
+#define        DS_MASK          7
+#define        DL_MASK          7
+#define        DA_MASK          7
+#define        ICE_MASK        0x80000000
+#define        DCE_MASK        0x40000000
+
+#define CP0_BRCM_CONFIG0       $22, 0
+#define CP0_BRCM_MODE          $22, 1
+#define        CP0_CONFIG_K0_MASK      7
+
+#define CP0_ICACHE_TAG_LO      $28
+#define CP0_ICACHE_DATA_LO     $28, 1
+#define CP0_DCACHE_TAG_LO      $28, 2
+#define CP0_D_SEC_CACHE_DATA_LO        $28, 3
+#define CP0_ICACHE_TAG_HI      $29
+#define CP0_ICACHE_DATA_HI     $29, 1
+#define CP0_DCACHE_TAG_HI      $29, 2
+
+#define CP0_BRCM_MODE_Luc_MASK         (1 << 11)
+#define        CP0_BRCM_CONFIG0_CWF_MASK       (1 << 20)
+#define        CP0_BRCM_CONFIG0_TSE_MASK       (1 << 19)
+#define CP0_BRCM_MODE_SET_MASK         (1 << 7)
+#define CP0_BRCM_MODE_ClkRATIO_MASK    (7 << 4)
+#define CP0_BRCM_MODE_BrPRED_MASK      (3 << 24)
+#define CP0_BRCM_MODE_BrPRED_SHIFT     24
+#define CP0_BRCM_MODE_BrHIST_MASK      (0x1f << 20)
+#define CP0_BRCM_MODE_BrHIST_SHIFT     20
+
+/* ZSC L2 Cache Register Access Register Definitions */
+#define BRCM_ZSC_ALL_REGS_SELECT               0x7 << 24
+
+#define BRCM_ZSC_CONFIG_REG                    0 << 3
+#define BRCM_ZSC_REQ_BUFFER_REG                        2 << 3
+#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0                4 << 3
+#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1                6 << 3
+#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2                8 << 3
+
+#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0                0xa << 3
+#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1                0xc << 3
+
+#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0                0xe << 3
+#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1                0x10 << 3
+
+#define BRCM_ZSC_CONFIG_LMB1En                 1 << (15)
+#define BRCM_ZSC_CONFIG_LMB0En                 1 << (14)
+
+/* branch predition values */
+
+#define BRCM_BrPRED_ALL_TAKEN          (0x0)
+#define BRCM_BrPRED_ALL_NOT_TAKEN      (0x1)
+#define BRCM_BrPRED_BHT_ENABLE         (0x2)
+#define BRCM_BrPRED_PREDICT_BACKWARD   (0x3)
+
+
+
+.align 2
+/*
+ * Function:   size_i_cache
+ * Arguments:  None
+ * Returns:    v0 = i cache size, v1 = I cache line size
+ * Description: compute the I-cache size and I-cache line size
+ * Trashes:    v0, v1, a0, t0
+ *
+ *     pseudo code:
+ *
+ */
+
+LEAF(size_i_cache)
+       .set    noreorder
+
+       mfc0    a0, CP0_CONFIG, 1
+       move    t0, a0
+
+       /*
+        * Determine sets per way: IS
+        *
+        * This field contains the number of sets (i.e., indices) per way of
+        * the instruction cache:
+        * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
+        * vi) 0x5 - 0x7: Reserved.
+        */
+
+       srl     a0, a0, IS_SHIFT
+       and     a0, a0, IS_MASK
+
+       /* sets per way = (64<<IS) */
+
+       li      v0, 0x40
+       sllv    v0, v0, a0
+
+       /*
+        * Determine line size
+        *
+        * This field contains the line size of the instruction cache:
+        * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
+        * 0x5: 64 bytes, iv) the rest: Reserved.
+        */
+
+       move    a0, t0
+
+       srl     a0, a0, IL_SHIFT
+       and     a0, a0, IL_MASK
+
+       beqz    a0, no_i_cache
+       nop
+
+       /* line size = 2 ^ (IL+1) */
+
+       addi    a0, a0, 1
+       li      v1, 1
+       sll     v1, v1, a0
+
+       /* v0 now have sets per way, multiply it by line size now
+        * that will give the set size
+        */
+
+       sll     v0, v0, a0
+
+       /*
+        * Determine set associativity
+        *
+        * This field contains the set associativity of the instruction cache.
+        * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
+        * 4-way, v) 0x4 - 0x7: Reserved.
+        */
+
+       move    a0, t0
+
+       srl     a0, a0, IA_SHIFT
+       and     a0, a0, IA_MASK
+       addi    a0, a0, 0x1
+
+       /* v0 has the set size, multiply it by
+        * set associativiy, to get the cache size
+        */
+
+       multu   v0, a0  /*multu is interlocked, so no need to insert nops */
+       mflo    v0
+       b       1f
+       nop
+
+no_i_cache:
+       move    v0, zero
+       move    v1, zero
+1:
+       jr      ra
+       nop
+       .set    reorder
+
+END(size_i_cache)
+
+/*
+ * Function:   size_d_cache
+ * Arguments:  None
+ * Returns:    v0 = d cache size, v1 = d cache line size
+ * Description: compute the D-cache size and D-cache line size.
+ * Trashes:    v0, v1, a0, t0
+ *
+ */
+
+LEAF(size_d_cache)
+       .set    noreorder
+
+       mfc0    a0, CP0_CONFIG, 1
+       move    t0, a0
+
+       /*
+        * Determine sets per way: IS
+        *
+        * This field contains the number of sets (i.e., indices) per way of
+        * the instruction cache:
+        * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
+        * vi) 0x5 - 0x7: Reserved.
+        */
+
+       srl     a0, a0, DS_SHIFT
+       and     a0, a0, DS_MASK
+
+       /* sets per way = (64<<IS) */
+
+       li      v0, 0x40
+       sllv    v0, v0, a0
+
+       /*
+        * Determine line size
+        *
+        * This field contains the line size of the instruction cache:
+        * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
+        * 0x5: 64 bytes, iv) the rest: Reserved.
+        */
+       move    a0, t0
+
+       srl     a0, a0, DL_SHIFT
+       and     a0, a0, DL_MASK
+
+       beqz    a0, no_d_cache
+       nop
+
+       /* line size = 2 ^ (IL+1) */
+
+       addi    a0, a0, 1
+       li      v1, 1
+       sll     v1, v1, a0
+
+       /* v0 now have sets per way, multiply it by line size now
+        * that will give the set size
+        */
+
+       sll     v0, v0, a0
+
+       /* determine set associativity
+        *
+        * This field contains the set associativity of the instruction cache.
+        * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
+        * 4-way, v) 0x4 - 0x7: Reserved.
+        */
+
+       move    a0, t0
+
+       srl     a0, a0, DA_SHIFT
+       and     a0, a0, DA_MASK
+       addi    a0, a0, 0x1
+
+       /* v0 has the set size, multiply it by
+        * set associativiy, to get the cache size
+        */
+
+       multu   v0, a0  /*multu is interlocked, so no need to insert nops */
+       mflo    v0
+
+       b       1f
+       nop
+
+no_d_cache:
+       move    v0, zero
+       move    v1, zero
+1:
+       jr      ra
+       nop
+       .set    reorder
+
+END(size_d_cache)
+
+
+/*
+ * Function: enable_ID
+ * Arguments:  None
+ * Returns:    None
+ * Description: Enable I and D caches, initialize I and D-caches, also set
+ *             hardware delay for d-cache (TP0).
+ * Trashes:    t0
+ *
+ */
+       .global enable_ID
+       .ent    enable_ID
+       .set    noreorder
+enable_ID:
+       mfc0    t0, CP0_BRCM_CONFIG0
+       or      t0, t0, (ICE_MASK | DCE_MASK)
+       mtc0    t0, CP0_BRCM_CONFIG0
+       jr      ra
+       nop
+
+       .end    enable_ID
+       .set    reorder
+
+
+/*
+ * Function: l1_init
+ * Arguments:  None
+ * Returns:    None
+ * Description: Enable I and D caches, and initialize I and D-caches
+ * Trashes:    a0, v0, v1, t0, t1, t2, t8
+ *
+ */
+       .globl  l1_init
+       .ent    l1_init
+       .set    noreorder
+l1_init:
+
+       /* save return address */
+       move    t8, ra
+
+
+       /* initialize I and D cache Data and Tag registers.  */
+       mtc0    zero, CP0_ICACHE_TAG_LO
+       mtc0    zero, CP0_ICACHE_TAG_HI
+       mtc0    zero, CP0_ICACHE_DATA_LO
+       mtc0    zero, CP0_ICACHE_DATA_HI
+       mtc0    zero, CP0_DCACHE_TAG_LO
+       mtc0    zero, CP0_DCACHE_TAG_HI
+
+       /* Enable Caches before Clearing. If the caches are disabled
+        * then the cache operations to clear the cache will be ignored
+        */
+
+       jal     enable_ID
+       nop
+
+       jal     size_i_cache    /* v0 = i-cache size, v1 = i-cache line size */
+       nop
+
+       /* run uncached in kseg 1 */
+       la      k0, 1f
+       lui     k1, 0x2000
+       or      k0, k1, k0
+       jr      k0
+       nop
+1:
+
+       /*
+        * set K0 cache mode
+        */
+
+       mfc0    t0, CP0_CONFIG
+       and     t0, t0, ~CP0_CONFIG_K0_MASK
+       or      t0, t0, 3       /* Write Back mode */
+       mtc0    t0, CP0_CONFIG
+
+       /*
+        * Initialize instruction cache.
+        */
+
+       li      a0, KSEG0
+       cacheop(a0, v0, v1, Index_Store_Tag_I)
+
+       /*
+        * Now we can run from I-$, kseg 0
+        */
+       la      k0, 1f
+       lui     k1, 0x2000
+       or      k0, k1, k0
+       xor     k0, k1, k0
+       jr      k0
+       nop
+1:
+       /*
+        * Initialize data cache.
+        */
+
+       jal     size_d_cache    /* v0 = d-cache size, v1 = d-cache line size */
+       nop
+
+
+       li      a0, KSEG0
+       cacheop(a0, v0, v1, Index_Store_Tag_D)
+
+       jr      t8
+       nop
+
+       .end    l1_init
+       .set    reorder
+
+
+/*
+ * Function:   set_other_config
+ * Arguments:  none
+ * Returns:    None
+ * Description: initialize other remainder configuration to defaults.
+ * Trashes:    t0, t1
+ *
+ *     pseudo code:
+ *
+ */
+LEAF(set_other_config)
+       .set noreorder
+
+       /* enable Bus error for I-fetch */
+       mfc0    t0, CP0_CACHEERR, 0
+       li      t1, 0x4
+       or      t0, t1
+       mtc0    t0, CP0_CACHEERR, 0
+
+       /* enable Bus error for Load */
+       mfc0    t0, CP0_CACHEERR, 1
+       li      t1, 0x4
+       or      t0, t1
+       mtc0    t0, CP0_CACHEERR, 1
+
+       /* enable Bus Error for Store */
+       mfc0    t0, CP0_CACHEERR, 2
+       li      t1, 0x4
+       or      t0, t1
+       mtc0    t0, CP0_CACHEERR, 2
+
+       jr      ra
+       nop
+       .set reorder
+END(set_other_config)
+
+/*
+ * Function:   set_branch_pred
+ * Arguments:  none
+ * Returns:    None
+ * Description:
+ * Trashes:    t0, t1
+ *
+ *     pseudo code:
+ *
+ */
+
+LEAF(set_branch_pred)
+       .set noreorder
+       mfc0    t0, CP0_BRCM_MODE
+       li      t1, ~(CP0_BRCM_MODE_BrPRED_MASK | CP0_BRCM_MODE_BrHIST_MASK )
+       and     t0, t0, t1
+
+       /* enable Branch prediction */
+       li      t1, BRCM_BrPRED_BHT_ENABLE
+       sll     t1, CP0_BRCM_MODE_BrPRED_SHIFT
+       or      t0, t0, t1
+
+       /* set history count to 8 */
+       li      t1, 8
+       sll     t1, CP0_BRCM_MODE_BrHIST_SHIFT
+       or      t0, t0, t1
+
+       mtc0    t0, CP0_BRCM_MODE
+       jr      ra
+       nop
+       .set    reorder
+END(set_branch_pred)
+
+
+/*
+ * Function:   set_luc
+ * Arguments:  set link uncached.
+ * Returns:    None
+ * Description:
+ * Trashes:    t0, t1
+ *
+ */
+LEAF(set_luc)
+       .set noreorder
+       mfc0    t0, CP0_BRCM_MODE
+       li      t1, ~(CP0_BRCM_MODE_Luc_MASK)
+       and     t0, t0, t1
+
+       /* set Luc */
+       ori     t0, t0, CP0_BRCM_MODE_Luc_MASK
+
+       mtc0    t0, CP0_BRCM_MODE
+       jr      ra
+       nop
+       .set    reorder
+END(set_luc)
+
+/*
+ * Function:   set_cwf_tse
+ * Arguments:  set CWF and TSE bits
+ * Returns:    None
+ * Description:
+ * Trashes:    t0, t1
+ *
+ */
+LEAF(set_cwf_tse)
+       .set noreorder
+       mfc0    t0, CP0_BRCM_CONFIG0
+       li      t1, (CP0_BRCM_CONFIG0_CWF_MASK | CP0_BRCM_CONFIG0_TSE_MASK)
+       or      t0, t0, t1
+
+       mtc0    t0, CP0_BRCM_CONFIG0
+       jr      ra
+       nop
+       .set    reorder
+END(set_cwf_tse)
+
+/*
+ * Function:   set_clock_ratio
+ * Arguments:  set clock ratio specified by a0
+ * Returns:    None
+ * Description:
+ * Trashes:    v0, v1, a0, a1
+ *
+ *     pseudo code:
+ *
+ */
+LEAF(set_clock_ratio)
+       .set noreorder
+
+       mfc0    t0, CP0_BRCM_MODE
+       li      t1, ~(CP0_BRCM_MODE_SET_MASK | CP0_BRCM_MODE_ClkRATIO_MASK)
+       and     t0, t0, t1
+       li      t1, CP0_BRCM_MODE_SET_MASK
+       or      t0, t0, t1
+       or      t0, t0, a0
+       mtc0    t0, CP0_BRCM_MODE
+       jr      ra
+       nop
+       .set    reorder
+END(set_clock_ratio)
+/*
+ * Function: set_zephyr
+ * Arguments:  None
+ * Returns:    None
+ * Description: Set any zephyr bits
+ * Trashes:    t0 & t1
+ *
+ */
+LEAF(set_zephyr)
+       .set    noreorder
+
+       /* enable read/write of CP0 #22 sel. 8 */
+       li      t0, 0x5a455048
+       .word   0x4088b00f      /* mtc0    t0, $22, 15 */
+
+       .word   0x4008b008      /* mfc0    t0, $22, 8 */
+       li      t1, 0x09008000  /* turn off pref, jtb */
+       or      t0, t0, t1
+       .word   0x4088b008      /* mtc0    t0, $22, 8 */
+       sync
+
+       /* disable read/write of CP0 #22 sel 8 */
+       li      t0, 0x0
+       .word   0x4088b00f      /* mtc0    t0, $22, 15 */
+
+
+       jr      ra
+       nop
+       .set reorder
+
+END(set_zephyr)
+
+
+/*
+ * Function:   set_llmb
+ * Arguments:  a0=0 disable llmb, a0=1 enables llmb
+ * Returns:    None
+ * Description:
+ * Trashes:    t0, t1, t2
+ *
+ *      pseudo code:
+ *
+ */
+LEAF(set_llmb)
+       .set noreorder
+
+       li      t2, 0x90000000 | BRCM_ZSC_ALL_REGS_SELECT | BRCM_ZSC_CONFIG_REG
+       sync
+       cache   0x7, 0x0(t2)
+       sync
+       mfc0    t0, CP0_D_SEC_CACHE_DATA_LO
+       li      t1, ~(BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
+       and     t0, t0, t1
+
+       beqz    a0, svlmb
+       nop
+
+enable_lmb:
+       li      t1, (BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
+       or      t0, t0, t1
+
+svlmb:
+       mtc0    t0, CP0_D_SEC_CACHE_DATA_LO
+       sync
+       cache   0xb, 0x0(t2)
+       sync
+
+       jr      ra
+       nop
+       .set reorder
+
+END(set_llmb)
+/*
+ * Function:   core_init
+ * Arguments:  none
+ * Returns:    None
+ * Description: initialize core related configuration
+ * Trashes:    v0,v1,a0,a1,t8
+ *
+ *     pseudo code:
+ *
+ */
+       .globl  core_init
+       .ent    core_init
+       .set    noreorder
+core_init:
+       move    t8, ra
+
+       /* set Zephyr bits. */
+       bal     set_zephyr
+       nop
+
+#if ENABLE_FPU==1
+       /* initialize the Floating point unit (both TPs) */
+       bal     init_fpu
+       nop
+#endif
+
+       /* set low latency memory bus */
+       li      a0, 1
+       bal     set_llmb
+       nop
+
+       /* set branch prediction (TP0 only) */
+       bal     set_branch_pred
+       nop
+
+       /* set link uncached */
+       bal     set_luc
+       nop
+
+       /* set CWF and TSE */
+       bal     set_cwf_tse
+       nop
+
+       /*
+        *set clock ratio by setting 1 to 'set'
+        * and 0 to ClkRatio, (TP0 only)
+        */
+       li      a0, 0
+       bal     set_clock_ratio
+       nop
+
+       /* set other configuration to defaults */
+       bal     set_other_config
+       nop
+
+       move    ra, t8
+       jr      ra
+       nop
+
+       .set reorder
+       .end    core_init
+
+/*
+ * Function:   clear_jump_target_buffer
+ * Arguments:  None
+ * Returns:    None
+ * Description:
+ * Trashes:    t0, t1, t2
+ *
+ */
+#define RESET_CALL_RETURN_STACK_THIS_THREAD            (0x06<<16)
+#define RESET_JUMP_TARGET_BUFFER_THIS_THREAD           (0x04<<16)
+#define JTB_CS_CNTL_MASK                               (0xFF<<16)
+
+       .globl  clear_jump_target_buffer
+       .ent    clear_jump_target_buffer
+       .set    noreorder
+clear_jump_target_buffer:
+
+       mfc0    t0, $22, 2
+       nop
+       nop
+
+       li      t1, ~JTB_CS_CNTL_MASK
+       and     t0, t0, t1
+       li      t2, RESET_CALL_RETURN_STACK_THIS_THREAD
+       or      t0, t0, t2
+       mtc0    t0, $22, 2
+       nop
+       nop
+
+       and     t0, t0, t1
+       li      t2, RESET_JUMP_TARGET_BUFFER_THIS_THREAD
+       or      t0, t0, t2
+       mtc0    t0, $22, 2
+       nop
+       nop
+       jr      ra
+       nop
+
+       .end    clear_jump_target_buffer
+       .set    reorder
+/*
+ * Function:   bmips_cache_init
+ * Arguments:  None
+ * Returns:    None
+ * Description: Enable I and D caches, and initialize I and D-caches
+ * Trashes:    v0, v1, t0, t1, t2, t5, t7, t8
+ *
+ */
+       .globl  bmips_5xxx_init
+       .ent    bmips_5xxx_init
+       .set    noreorder
+bmips_5xxx_init:
+
+       /* save return address and A0 */
+       move    t7, ra
+       move    t5, a0
+
+       jal     l1_init
+       nop
+
+       jal     core_init
+       nop
+
+       jal     clear_jump_target_buffer
+       nop
+
+       mtc0    zero, CP0_CAUSE
+
+       move    a0, t5
+       jr      t7
+       nop
+
+       .end    bmips_5xxx_init
+       .set    reorder
+
+
+#endif
index 86495072a922f31e0214cad3b6ac71c10aaf5fa8..921a5fa55da6eae3ea704d5e0eeb6101da0217ef 100644 (file)
@@ -88,12 +88,13 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
        li      k1, (1 << 19)
        mfc0    k0, CP0_STATUS
        and     k0, k1
-       beqz    k0, bmips_smp_entry
+       beqz    k0, soft_reset
 
 #if defined(CONFIG_CPU_BMIPS5000)
        mfc0    k0, CP0_PRID
        li      k1, PRID_IMP_BMIPS5000
-       andi    k0, 0xff00
+       /* mask with PRID_IMP_BMIPS5000 to cover both variants */
+       andi    k0, PRID_IMP_BMIPS5000
        bne     k0, k1, 1f
 
        /* if we're not on core 0, this must be the SMP boot signal */
@@ -125,13 +126,48 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
        .set    arch=r4000
        eret
 
+#ifdef CONFIG_SMP
+soft_reset:
+
+#if defined(CONFIG_CPU_BMIPS5000)
+       mfc0    k0, CP0_PRID
+       andi    k0, 0xff00
+       li      k1, PRID_IMP_BMIPS5200
+       bne     k0, k1, bmips_smp_entry
+
+        /* if running on TP 1, jump  to  bmips_smp_entry */
+        mfc0    k0, $22
+        li      k1, (1 << 24)
+        and     k1, k0
+        bnez    k1, bmips_smp_entry
+        nop
+
+        /*
+         * running on TP0, can not be core 0 (the boot core).
+         * Check for soft reset.  Indicates a warm boot
+         */
+        mfc0    k0, $12
+        li      k1, (1 << 20)
+        and     k0, k1
+        beqz    k0, bmips_smp_entry
+
+        /*
+         * Warm boot.
+         * Cache init is only done on TP0
+         */
+        la      k0, bmips_5xxx_init
+        jalr    k0
+        nop
+
+        b       bmips_smp_entry
+        nop
+#endif
+
 /***********************************************************************
  * CPU1 reset vector (used for the initial boot only)
  * This is still part of bmips_reset_nmi_vec().
  ***********************************************************************/
 
-#ifdef CONFIG_SMP
-
 bmips_smp_entry:
 
        /* set up CP0 STATUS; enable FPU */
@@ -166,10 +202,12 @@ bmips_smp_entry:
 2:
 #endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
 #if defined(CONFIG_CPU_BMIPS5000)
-       /* set exception vector base */
+       /* mask with PRID_IMP_BMIPS5000 to cover both variants */
        li      k1, PRID_IMP_BMIPS5000
+       andi    k0, PRID_IMP_BMIPS5000
        bne     k0, k1, 3f
 
+       /* set exception vector base */
        la      k0, ebase
        lw      k0, 0(k0)
        mtc0    k0, $15, 1
@@ -263,6 +301,8 @@ LEAF(bmips_enable_xks01)
 #endif /* CONFIG_CPU_BMIPS4380 */
 #if defined(CONFIG_CPU_BMIPS5000)
        li      t1, PRID_IMP_BMIPS5000
+       /* mask with PRID_IMP_BMIPS5000 to cover both variants */
+       andi    t2, PRID_IMP_BMIPS5000
        bne     t2, t1, 2f
 
        mfc0    t0, $22, 5
index d8f9b357b2226bef0141c8ed6340baa8fb7c0f4f..ceca6cc41b2b8b0c11f637fa639e6d037e589404 100644 (file)
@@ -688,21 +688,9 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
                        }
                        lose_fpu(1);    /* Save FPU state for the emulator. */
                        reg = insn.i_format.rt;
-                       bit = 0;
-                       switch (insn.i_format.rs) {
-                       case bc1eqz_op:
-                               /* Test bit 0 */
-                               if (get_fpr32(&current->thread.fpu.fpr[reg], 0)
-                                   & 0x1)
-                                       bit = 1;
-                               break;
-                       case bc1nez_op:
-                               /* Test bit 0 */
-                               if (!(get_fpr32(&current->thread.fpu.fpr[reg], 0)
-                                     & 0x1))
-                                       bit = 1;
-                               break;
-                       }
+                       bit = get_fpr32(&current->thread.fpu.fpr[reg], 0) & 0x1;
+                       if (insn.i_format.rs == bc1eqz_op)
+                               bit = !bit;
                        own_fpu(1);
                        if (bit)
                                epc = epc + 4 +
index 8dfe6a6e14809b992774bd7362761021b802bd15..e4c21bbf9422b8238bf908648a9d7feae9bb6f72 100644 (file)
@@ -28,6 +28,83 @@ static int mips_next_event(unsigned long delta,
        return res;
 }
 
+/**
+ * calculate_min_delta() - Calculate a good minimum delta for mips_next_event().
+ *
+ * Running under virtualisation can introduce overhead into mips_next_event() in
+ * the form of hypervisor emulation of CP0_Count/CP0_Compare registers,
+ * potentially with an unnatural frequency, which makes a fixed min_delta_ns
+ * value inappropriate as it may be too small.
+ *
+ * It can also introduce occasional latency from the guest being descheduled.
+ *
+ * This function calculates a good minimum delta based roughly on the 75th
+ * percentile of the time taken to do the mips_next_event() sequence, in order
+ * to handle potentially higher overhead while also eliminating outliers due to
+ * unpredictable hypervisor latency (which can be handled by retries).
+ *
+ * Return:     An appropriate minimum delta for the clock event device.
+ */
+static unsigned int calculate_min_delta(void)
+{
+       unsigned int cnt, i, j, k, l;
+       unsigned int buf1[4], buf2[3];
+       unsigned int min_delta;
+
+       /*
+        * Calculate the median of 5 75th percentiles of 5 samples of how long
+        * it takes to set CP0_Compare = CP0_Count + delta.
+        */
+       for (i = 0; i < 5; ++i) {
+               for (j = 0; j < 5; ++j) {
+                       /*
+                        * This is like the code in mips_next_event(), and
+                        * directly measures the borderline "safe" delta.
+                        */
+                       cnt = read_c0_count();
+                       write_c0_compare(cnt);
+                       cnt = read_c0_count() - cnt;
+
+                       /* Sorted insert into buf1 */
+                       for (k = 0; k < j; ++k) {
+                               if (cnt < buf1[k]) {
+                                       l = min_t(unsigned int,
+                                                 j, ARRAY_SIZE(buf1) - 1);
+                                       for (; l > k; --l)
+                                               buf1[l] = buf1[l - 1];
+                                       break;
+                               }
+                       }
+                       if (k < ARRAY_SIZE(buf1))
+                               buf1[k] = cnt;
+               }
+
+               /* Sorted insert of 75th percentile into buf2 */
+               for (k = 0; k < i; ++k) {
+                       if (buf1[ARRAY_SIZE(buf1) - 1] < buf2[k]) {
+                               l = min_t(unsigned int,
+                                         i, ARRAY_SIZE(buf2) - 1);
+                               for (; l > k; --l)
+                                       buf2[l] = buf2[l - 1];
+                               break;
+                       }
+               }
+               if (k < ARRAY_SIZE(buf2))
+                       buf2[k] = buf1[ARRAY_SIZE(buf1) - 1];
+       }
+
+       /* Use 2 * median of 75th percentiles */
+       min_delta = buf2[ARRAY_SIZE(buf2) - 1] * 2;
+
+       /* Don't go too low */
+       if (min_delta < 0x300)
+               min_delta = 0x300;
+
+       pr_debug("%s: median 75th percentile=%#x, min_delta=%#x\n",
+                __func__, buf2[ARRAY_SIZE(buf2) - 1], min_delta);
+       return min_delta;
+}
+
 DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 int cp0_timer_irq_installed;
 
@@ -177,7 +254,7 @@ int r4k_clockevent_init(void)
 {
        unsigned int cpu = smp_processor_id();
        struct clock_event_device *cd;
-       unsigned int irq;
+       unsigned int irq, min_delta;
 
        if (!cpu_has_counter || !mips_hpt_frequency)
                return -ENXIO;
@@ -203,7 +280,8 @@ int r4k_clockevent_init(void)
 
        /* Calculate the min / max delta */
        cd->max_delta_ns        = clockevent_delta2ns(0x7fffffff, cd);
-       cd->min_delta_ns        = clockevent_delta2ns(0x300, cd);
+       min_delta               = calculate_min_delta();
+       cd->min_delta_ns        = clockevent_delta2ns(min_delta, cd);
 
        cd->rating              = 300;
        cd->irq                 = irq;
index ac81edd44563119dbf6cf6fa0c9154afb9c47b98..51b98dc371b39af01264328e6108f0995472c127 100644 (file)
 #include <asm/mipsmtregs.h>
 #include <asm/pm.h>
 
+#define GCR_CPC_BASE_OFS       0x0088
 #define GCR_CL_COHERENCE_OFS   0x2008
 #define GCR_CL_ID_OFS          0x2028
 
+#define CPC_CL_VC_RUN_OFS      0x2028
+
 .extern mips_cm_base
 
 .set noreorder
         nop
        .endm
 
+       /*
+        * Set dest to non-zero if the core supports MIPSr6 multithreading
+        * (ie. VPs), else zero. If MIPSr6 multithreading is not supported then
+        * branch to nomt.
+        */
+       .macro  has_vp  dest, nomt
+       mfc0    \dest, CP0_CONFIG, 1
+       bgez    \dest, \nomt
+        mfc0   \dest, CP0_CONFIG, 2
+       bgez    \dest, \nomt
+        mfc0   \dest, CP0_CONFIG, 3
+       bgez    \dest, \nomt
+        mfc0   \dest, CP0_CONFIG, 4
+       bgez    \dest, \nomt
+        mfc0   \dest, CP0_CONFIG, 5
+       andi    \dest, \dest, MIPS_CONF5_VP
+       beqz    \dest, \nomt
+        nop
+       .endm
+
+       /* Calculate an uncached address for the CM GCRs */
+       .macro  cmgcrb  dest
+       .set    push
+       .set    noat
+       MFC0    $1, CP0_CMGCRBASE
+       PTR_SLL $1, $1, 4
+       PTR_LI  \dest, UNCAC_BASE
+       PTR_ADDU \dest, \dest, $1
+       .set    pop
+       .endm
+
 .section .text.cps-vec
 .balign 0x1000
 
@@ -90,120 +124,64 @@ not_nmi:
        li      t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
        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
-       addiu   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
-       addiu   t2, t2, 1
-       mul     t1, t1, t0
-       mul     t1, t1, t2
-
-       li      a0, CKSEG0
-       PTR_ADD a1, a0, t1
-1:     cache   Index_Store_Tag_I, 0(a0)
-       PTR_ADD a0, a0, t0
-       bne     a0, a1, 1b
+       /* Skip cache & coherence setup if we're already coherent */
+       cmgcrb  v1
+       lw      s7, GCR_CL_COHERENCE_OFS(v1)
+       bnez    s7, 1f
         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
-       addiu   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
-       addiu   t2, t2, 1
-       mul     t1, t1, t0
-       mul     t1, t1, t2
+       /* Initialize the L1 caches */
+       jal     mips_cps_cache_init
+        nop
 
-       li      a0, CKSEG0
-       PTR_ADDU a1, a0, t1
-       PTR_SUBU a1, a1, t0
-1:     cache   Index_Store_Tag_D, 0(a0)
-       bne     a0, a1, 1b
-        PTR_ADD a0, a0, t0
-dcache_done:
+       /* Enter the coherent domain */
+       li      t0, 0xff
+       sw      t0, GCR_CL_COHERENCE_OFS(v1)
+       ehb
 
        /* Set Kseg0 CCA to that in s0 */
-       mfc0    t0, CP0_CONFIG
+1:     mfc0    t0, CP0_CONFIG
        ori     t0, 0x7
        xori    t0, 0x7
        or      t0, t0, s0
        mtc0    t0, CP0_CONFIG
        ehb
 
-       /* Calculate an uncached address for the CM GCRs */
-       MFC0    v1, CP0_CMGCRBASE
-       PTR_SLL v1, v1, 4
-       PTR_LI  t0, UNCAC_BASE
-       PTR_ADDU v1, v1, t0
-
-       /* Enter the coherent domain */
-       li      t0, 0xff
-       sw      t0, GCR_CL_COHERENCE_OFS(v1)
-       ehb
-
        /* Jump to kseg0 */
        PTR_LA  t0, 1f
        jr      t0
         nop
 
        /*
-        * We're up, cached & coherent. Perform any further required core-level
-        * initialisation.
+        * We're up, cached & coherent. Perform any EVA initialization necessary
+        * before we access memory.
         */
-1:     jal     mips_cps_core_init
+1:     eva_init
+
+       /* Retrieve boot configuration pointers */
+       jal     mips_cps_get_bootcfg
         nop
 
-       /* Do any EVA initialization if necessary */
-       eva_init
+       /* Skip core-level init if we started up coherent */
+       bnez    s7, 1f
+        nop
+
+       /* Perform any further required core-level initialisation */
+       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.
         */
+       move    a1, t9
        jal     mips_cps_boot_vpes
-        nop
+        move   a0, v0
 
        /* Off we go! */
-       PTR_L   t1, VPEBOOTCFG_PC(v0)
-       PTR_L   gp, VPEBOOTCFG_GP(v0)
-       PTR_L   sp, VPEBOOTCFG_SP(v0)
+1:     PTR_L   t1, VPEBOOTCFG_PC(v1)
+       PTR_L   gp, VPEBOOTCFG_GP(v1)
+       PTR_L   sp, VPEBOOTCFG_SP(v1)
        jr      t1
         nop
        END(mips_cps_core_entry)
@@ -245,7 +223,6 @@ LEAF(excep_intex)
 
 .org 0x480
 LEAF(excep_ejtag)
-       DUMP_EXCEP("EJTAG")
        PTR_LA  k0, ejtag_debug_handler
        jr      k0
         nop
@@ -323,22 +300,35 @@ LEAF(mips_cps_core_init)
         nop
        END(mips_cps_core_init)
 
-LEAF(mips_cps_boot_vpes)
-       /* Retrieve CM base address */
-       PTR_LA  t0, mips_cm_base
-       PTR_L   t0, 0(t0)
-
+/**
+ * mips_cps_get_bootcfg() - retrieve boot configuration pointers
+ *
+ * Returns: pointer to struct core_boot_config in v0, pointer to
+ *          struct vpe_boot_config in v1, VPE ID in t9
+ */
+LEAF(mips_cps_get_bootcfg)
        /* Calculate a pointer to this cores struct core_boot_config */
+       cmgcrb  t0
        lw      t0, GCR_CL_ID_OFS(t0)
        li      t1, COREBOOTCFG_SIZE
        mul     t0, t0, t1
        PTR_LA  t1, mips_cps_core_bootcfg
        PTR_L   t1, 0(t1)
-       PTR_ADDU t0, t0, t1
+       PTR_ADDU v0, t0, t1
 
        /* Calculate this VPEs ID. If the core doesn't support MT use 0 */
        li      t9, 0
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_CPU_MIPSR6)
+       has_vp  ta2, 1f
+
+       /*
+        * Assume non-contiguous numbering. Perhaps some day we'll need
+        * to handle contiguous VP numbering, but no such systems yet
+        * exist.
+        */
+       mfc0    t9, $3, 1
+       andi    t9, t9, 0xff
+#elif defined(CONFIG_MIPS_MT_SMP)
        has_mt  ta2, 1f
 
        /* Find the number of VPEs present in the core */
@@ -362,22 +352,43 @@ LEAF(mips_cps_boot_vpes)
 
 1:     /* Calculate a pointer to this VPEs struct vpe_boot_config */
        li      t1, VPEBOOTCFG_SIZE
-       mul     v0, t9, t1
-       PTR_L   ta3, COREBOOTCFG_VPECONFIG(t0)
-       PTR_ADDU v0, v0, ta3
-
-#ifdef CONFIG_MIPS_MT_SMP
+       mul     v1, t9, t1
+       PTR_L   ta3, COREBOOTCFG_VPECONFIG(v0)
+       PTR_ADDU v1, v1, ta3
 
-       /* If the core doesn't support MT then return */
-       bnez    ta2, 1f
-        nop
        jr      ra
         nop
+       END(mips_cps_get_bootcfg)
+
+LEAF(mips_cps_boot_vpes)
+       PTR_L   ta2, COREBOOTCFG_VPEMASK(a0)
+       PTR_L   ta3, COREBOOTCFG_VPECONFIG(a0)
+
+#if defined(CONFIG_CPU_MIPSR6)
+
+       has_vp  t0, 5f
+
+       /* Find base address of CPC */
+       cmgcrb  t3
+       PTR_L   t1, GCR_CPC_BASE_OFS(t3)
+       PTR_LI  t2, ~0x7fff
+       and     t1, t1, t2
+       PTR_LI  t2, UNCAC_BASE
+       PTR_ADD t1, t1, t2
+
+       /* Set VC_RUN to the VPE mask */
+       PTR_S   ta2, CPC_CL_VC_RUN_OFS(t1)
+       ehb
+
+#elif defined(CONFIG_MIPS_MT)
 
        .set    push
        .set    mt
 
-1:     /* Enter VPE configuration state */
+       /* If the core doesn't support MT then return */
+       has_mt  t0, 5f
+
+       /* Enter VPE configuration state */
        dvpe
        PTR_LA  t1, 1f
        jr.hb   t1
@@ -388,7 +399,6 @@ LEAF(mips_cps_boot_vpes)
        ehb
 
        /* Loop through each VPE */
-       PTR_L   ta2, COREBOOTCFG_VPEMASK(t0)
        move    t8, ta2
        li      ta1, 0
 
@@ -465,7 +475,7 @@ LEAF(mips_cps_boot_vpes)
 
        /* Check whether this VPE is meant to be running */
        li      t0, 1
-       sll     t0, t0, t9
+       sll     t0, t0, a1
        and     t0, t0, t8
        bnez    t0, 2f
         nop
@@ -482,10 +492,84 @@ LEAF(mips_cps_boot_vpes)
 #endif /* CONFIG_MIPS_MT_SMP */
 
        /* Return */
-       jr      ra
+5:     jr      ra
         nop
        END(mips_cps_boot_vpes)
 
+LEAF(mips_cps_cache_init)
+       /*
+        * 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
+       addiu   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
+       addiu   t2, t2, 1
+       mul     t1, t1, t0
+       mul     t1, t1, t2
+
+       li      a0, CKSEG0
+       PTR_ADD a1, a0, t1
+1:     cache   Index_Store_Tag_I, 0(a0)
+       PTR_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
+       addiu   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
+       addiu   t2, t2, 1
+       mul     t1, t1, t0
+       mul     t1, t1, t2
+
+       li      a0, CKSEG0
+       PTR_ADDU a1, a0, t1
+       PTR_SUBU a1, a1, t0
+1:     cache   Index_Store_Tag_D, 0(a0)
+       bne     a0, a1, 1b
+        PTR_ADD a0, a0, t0
+dcache_done:
+
+       jr      ra
+        nop
+       END(mips_cps_cache_init)
+
 #if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM)
 
        /* Calculate a pointer to this CPUs struct mips_static_suspend_state */
index b725b713b9f8b56e3763784c18b0550dffd77b6d..5ac5c3e23460b72036ccd96d25296b7848841920 100644 (file)
@@ -539,6 +539,7 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
        switch (c->cputype) {
        case CPU_PROAPTIV:
        case CPU_P5600:
+       case CPU_P6600:
                /* proAptiv & related cores use Config6 to enable the FTLB */
                config = read_c0_config6();
                /* Clear the old probability value */
@@ -561,6 +562,19 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
                write_c0_config7(config | (calculate_ftlb_probability(c)
                                           << MIPS_CONF7_FTLBP_SHIFT));
                break;
+       case CPU_LOONGSON3:
+               /* Flush ITLB, DTLB, VTLB and FTLB */
+               write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB |
+                             LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB);
+               /* Loongson-3 cores use Config6 to enable the FTLB */
+               config = read_c0_config6();
+               if (enable)
+                       /* Enable FTLB */
+                       write_c0_config6(config & ~MIPS_CONF6_FTLBDIS);
+               else
+                       /* Disable FTLB */
+                       write_c0_config6(config | MIPS_CONF6_FTLBDIS);
+               break;
        default:
                return 1;
        }
@@ -634,6 +648,8 @@ static inline unsigned int decode_config1(struct cpuinfo_mips *c)
 
        if (config1 & MIPS_CONF1_MD)
                c->ases |= MIPS_ASE_MDMX;
+       if (config1 & MIPS_CONF1_PC)
+               c->options |= MIPS_CPU_PERF;
        if (config1 & MIPS_CONF1_WR)
                c->options |= MIPS_CPU_WATCH;
        if (config1 & MIPS_CONF1_CA)
@@ -673,18 +689,25 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
 
        if (config3 & MIPS_CONF3_SM) {
                c->ases |= MIPS_ASE_SMARTMIPS;
-               c->options |= MIPS_CPU_RIXI;
+               c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC;
        }
        if (config3 & MIPS_CONF3_RXI)
                c->options |= MIPS_CPU_RIXI;
+       if (config3 & MIPS_CONF3_CTXTC)
+               c->options |= MIPS_CPU_CTXTC;
        if (config3 & MIPS_CONF3_DSP)
                c->ases |= MIPS_ASE_DSP;
-       if (config3 & MIPS_CONF3_DSP2P)
+       if (config3 & MIPS_CONF3_DSP2P) {
                c->ases |= MIPS_ASE_DSP2P;
+               if (cpu_has_mips_r6)
+                       c->ases |= MIPS_ASE_DSP3;
+       }
        if (config3 & MIPS_CONF3_VINT)
                c->options |= MIPS_CPU_VINT;
        if (config3 & MIPS_CONF3_VEIC)
                c->options |= MIPS_CPU_VEIC;
+       if (config3 & MIPS_CONF3_LPA)
+               c->options |= MIPS_CPU_LPA;
        if (config3 & MIPS_CONF3_MT)
                c->ases |= MIPS_ASE_MIPSMT;
        if (config3 & MIPS_CONF3_ULRI)
@@ -695,6 +718,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
                c->ases |= MIPS_ASE_VZ;
        if (config3 & MIPS_CONF3_SC)
                c->options |= MIPS_CPU_SEGMENTS;
+       if (config3 & MIPS_CONF3_BI)
+               c->options |= MIPS_CPU_BADINSTR;
+       if (config3 & MIPS_CONF3_BP)
+               c->options |= MIPS_CPU_BADINSTRP;
        if (config3 & MIPS_CONF3_MSA)
                c->ases |= MIPS_ASE_MSA;
        if (config3 & MIPS_CONF3_PW) {
@@ -715,6 +742,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
        unsigned int newcf4;
        unsigned int mmuextdef;
        unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE;
+       unsigned long asid_mask;
 
        config4 = read_c0_config4();
 
@@ -773,7 +801,20 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
                }
        }
 
-       c->kscratch_mask = (config4 >> 16) & 0xff;
+       c->kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
+                               >> MIPS_CONF4_KSCREXIST_SHIFT;
+
+       asid_mask = MIPS_ENTRYHI_ASID;
+       if (config4 & MIPS_CONF4_AE)
+               asid_mask |= MIPS_ENTRYHI_ASIDX;
+       set_cpu_asid_mask(c, asid_mask);
+
+       /*
+        * Warn if the computed ASID mask doesn't match the mask the kernel
+        * is built for. This may indicate either a serious problem or an
+        * easy optimisation opportunity, but either way should be addressed.
+        */
+       WARN_ON(asid_mask != cpu_asid_mask(c));
 
        return config4 & MIPS_CONF_M;
 }
@@ -796,6 +837,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
        if (config5 & MIPS_CONF5_MVH)
                c->options |= MIPS_CPU_XPA;
 #endif
+       if (cpu_has_mips_r6 && (config5 & MIPS_CONF5_VP))
+               c->options |= MIPS_CPU_VP;
 
        return config5 & MIPS_CONF_M;
 }
@@ -826,17 +869,43 @@ static void decode_configs(struct cpuinfo_mips *c)
        if (ok)
                ok = decode_config5(c);
 
-       mips_probe_watch_registers(c);
-
-       if (cpu_has_rixi) {
-               /* Enable the RIXI exceptions */
-               set_c0_pagegrain(PG_IEC);
-               back_to_back_c0_hazard();
-               /* Verify the IEC bit is set */
-               if (read_c0_pagegrain() & PG_IEC)
-                       c->options |= MIPS_CPU_RIXIEX;
+       /* Probe the EBase.WG bit */
+       if (cpu_has_mips_r2_r6) {
+               u64 ebase;
+               unsigned int status;
+
+               /* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */
+               ebase = cpu_has_mips64r6 ? read_c0_ebase_64()
+                                        : (s32)read_c0_ebase();
+               if (ebase & MIPS_EBASE_WG) {
+                       /* WG bit already set, we can avoid the clumsy probe */
+                       c->options |= MIPS_CPU_EBASE_WG;
+               } else {
+                       /* Its UNDEFINED to change EBase while BEV=0 */
+                       status = read_c0_status();
+                       write_c0_status(status | ST0_BEV);
+                       irq_enable_hazard();
+                       /*
+                        * On pre-r6 cores, this may well clobber the upper bits
+                        * of EBase. This is hard to avoid without potentially
+                        * hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit.
+                        */
+                       if (cpu_has_mips64r6)
+                               write_c0_ebase_64(ebase | MIPS_EBASE_WG);
+                       else
+                               write_c0_ebase(ebase | MIPS_EBASE_WG);
+                       back_to_back_c0_hazard();
+                       /* Restore BEV */
+                       write_c0_status(status);
+                       if (read_c0_ebase() & MIPS_EBASE_WG) {
+                               c->options |= MIPS_CPU_EBASE_WG;
+                               write_c0_ebase(ebase);
+                       }
+               }
        }
 
+       mips_probe_watch_registers(c);
+
 #ifndef CONFIG_MIPS_CPS
        if (cpu_has_mips_r2_r6) {
                c->core = get_ebase_cpunum();
@@ -846,6 +915,235 @@ static void decode_configs(struct cpuinfo_mips *c)
 #endif
 }
 
+/*
+ * Probe for certain guest capabilities by writing config bits and reading back.
+ * Finally write back the original value.
+ */
+#define probe_gc0_config(name, maxconf, bits)                          \
+do {                                                                   \
+       unsigned int tmp;                                               \
+       tmp = read_gc0_##name();                                        \
+       write_gc0_##name(tmp | (bits));                                 \
+       back_to_back_c0_hazard();                                       \
+       maxconf = read_gc0_##name();                                    \
+       write_gc0_##name(tmp);                                          \
+} while (0)
+
+/*
+ * Probe for dynamic guest capabilities by changing certain config bits and
+ * reading back to see if they change. Finally write back the original value.
+ */
+#define probe_gc0_config_dyn(name, maxconf, dynconf, bits)             \
+do {                                                                   \
+       maxconf = read_gc0_##name();                                    \
+       write_gc0_##name(maxconf ^ (bits));                             \
+       back_to_back_c0_hazard();                                       \
+       dynconf = maxconf ^ read_gc0_##name();                          \
+       write_gc0_##name(maxconf);                                      \
+       maxconf |= dynconf;                                             \
+} while (0)
+
+static inline unsigned int decode_guest_config0(struct cpuinfo_mips *c)
+{
+       unsigned int config0;
+
+       probe_gc0_config(config, config0, MIPS_CONF_M);
+
+       if (config0 & MIPS_CONF_M)
+               c->guest.conf |= BIT(1);
+       return config0 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config1(struct cpuinfo_mips *c)
+{
+       unsigned int config1, config1_dyn;
+
+       probe_gc0_config_dyn(config1, config1, config1_dyn,
+                            MIPS_CONF_M | MIPS_CONF1_PC | MIPS_CONF1_WR |
+                            MIPS_CONF1_FP);
+
+       if (config1 & MIPS_CONF1_FP)
+               c->guest.options |= MIPS_CPU_FPU;
+       if (config1_dyn & MIPS_CONF1_FP)
+               c->guest.options_dyn |= MIPS_CPU_FPU;
+
+       if (config1 & MIPS_CONF1_WR)
+               c->guest.options |= MIPS_CPU_WATCH;
+       if (config1_dyn & MIPS_CONF1_WR)
+               c->guest.options_dyn |= MIPS_CPU_WATCH;
+
+       if (config1 & MIPS_CONF1_PC)
+               c->guest.options |= MIPS_CPU_PERF;
+       if (config1_dyn & MIPS_CONF1_PC)
+               c->guest.options_dyn |= MIPS_CPU_PERF;
+
+       if (config1 & MIPS_CONF_M)
+               c->guest.conf |= BIT(2);
+       return config1 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config2(struct cpuinfo_mips *c)
+{
+       unsigned int config2;
+
+       probe_gc0_config(config2, config2, MIPS_CONF_M);
+
+       if (config2 & MIPS_CONF_M)
+               c->guest.conf |= BIT(3);
+       return config2 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config3(struct cpuinfo_mips *c)
+{
+       unsigned int config3, config3_dyn;
+
+       probe_gc0_config_dyn(config3, config3, config3_dyn,
+                            MIPS_CONF_M | MIPS_CONF3_MSA | MIPS_CONF3_CTXTC);
+
+       if (config3 & MIPS_CONF3_CTXTC)
+               c->guest.options |= MIPS_CPU_CTXTC;
+       if (config3_dyn & MIPS_CONF3_CTXTC)
+               c->guest.options_dyn |= MIPS_CPU_CTXTC;
+
+       if (config3 & MIPS_CONF3_PW)
+               c->guest.options |= MIPS_CPU_HTW;
+
+       if (config3 & MIPS_CONF3_SC)
+               c->guest.options |= MIPS_CPU_SEGMENTS;
+
+       if (config3 & MIPS_CONF3_BI)
+               c->guest.options |= MIPS_CPU_BADINSTR;
+       if (config3 & MIPS_CONF3_BP)
+               c->guest.options |= MIPS_CPU_BADINSTRP;
+
+       if (config3 & MIPS_CONF3_MSA)
+               c->guest.ases |= MIPS_ASE_MSA;
+       if (config3_dyn & MIPS_CONF3_MSA)
+               c->guest.ases_dyn |= MIPS_ASE_MSA;
+
+       if (config3 & MIPS_CONF_M)
+               c->guest.conf |= BIT(4);
+       return config3 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config4(struct cpuinfo_mips *c)
+{
+       unsigned int config4;
+
+       probe_gc0_config(config4, config4,
+                        MIPS_CONF_M | MIPS_CONF4_KSCREXIST);
+
+       c->guest.kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
+                               >> MIPS_CONF4_KSCREXIST_SHIFT;
+
+       if (config4 & MIPS_CONF_M)
+               c->guest.conf |= BIT(5);
+       return config4 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config5(struct cpuinfo_mips *c)
+{
+       unsigned int config5, config5_dyn;
+
+       probe_gc0_config_dyn(config5, config5, config5_dyn,
+                        MIPS_CONF_M | MIPS_CONF5_MRP);
+
+       if (config5 & MIPS_CONF5_MRP)
+               c->guest.options |= MIPS_CPU_MAAR;
+       if (config5_dyn & MIPS_CONF5_MRP)
+               c->guest.options_dyn |= MIPS_CPU_MAAR;
+
+       if (config5 & MIPS_CONF5_LLB)
+               c->guest.options |= MIPS_CPU_RW_LLB;
+
+       if (config5 & MIPS_CONF_M)
+               c->guest.conf |= BIT(6);
+       return config5 & MIPS_CONF_M;
+}
+
+static inline void decode_guest_configs(struct cpuinfo_mips *c)
+{
+       unsigned int ok;
+
+       ok = decode_guest_config0(c);
+       if (ok)
+               ok = decode_guest_config1(c);
+       if (ok)
+               ok = decode_guest_config2(c);
+       if (ok)
+               ok = decode_guest_config3(c);
+       if (ok)
+               ok = decode_guest_config4(c);
+       if (ok)
+               decode_guest_config5(c);
+}
+
+static inline void cpu_probe_guestctl0(struct cpuinfo_mips *c)
+{
+       unsigned int guestctl0, temp;
+
+       guestctl0 = read_c0_guestctl0();
+
+       if (guestctl0 & MIPS_GCTL0_G0E)
+               c->options |= MIPS_CPU_GUESTCTL0EXT;
+       if (guestctl0 & MIPS_GCTL0_G1)
+               c->options |= MIPS_CPU_GUESTCTL1;
+       if (guestctl0 & MIPS_GCTL0_G2)
+               c->options |= MIPS_CPU_GUESTCTL2;
+       if (!(guestctl0 & MIPS_GCTL0_RAD)) {
+               c->options |= MIPS_CPU_GUESTID;
+
+               /*
+                * Probe for Direct Root to Guest (DRG). Set GuestCtl1.RID = 0
+                * first, otherwise all data accesses will be fully virtualised
+                * as if they were performed by guest mode.
+                */
+               write_c0_guestctl1(0);
+               tlbw_use_hazard();
+
+               write_c0_guestctl0(guestctl0 | MIPS_GCTL0_DRG);
+               back_to_back_c0_hazard();
+               temp = read_c0_guestctl0();
+
+               if (temp & MIPS_GCTL0_DRG) {
+                       write_c0_guestctl0(guestctl0);
+                       c->options |= MIPS_CPU_DRG;
+               }
+       }
+}
+
+static inline void cpu_probe_guestctl1(struct cpuinfo_mips *c)
+{
+       if (cpu_has_guestid) {
+               /* determine the number of bits of GuestID available */
+               write_c0_guestctl1(MIPS_GCTL1_ID);
+               back_to_back_c0_hazard();
+               c->guestid_mask = (read_c0_guestctl1() & MIPS_GCTL1_ID)
+                                               >> MIPS_GCTL1_ID_SHIFT;
+               write_c0_guestctl1(0);
+       }
+}
+
+static inline void cpu_probe_gtoffset(struct cpuinfo_mips *c)
+{
+       /* determine the number of bits of GTOffset available */
+       write_c0_gtoffset(0xffffffff);
+       back_to_back_c0_hazard();
+       c->gtoffset_mask = read_c0_gtoffset();
+       write_c0_gtoffset(0);
+}
+
+static inline void cpu_probe_vz(struct cpuinfo_mips *c)
+{
+       cpu_probe_guestctl0(c);
+       if (cpu_has_guestctl1)
+               cpu_probe_guestctl1(c);
+
+       cpu_probe_gtoffset(c);
+
+       decode_guest_configs(c);
+}
+
 #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
                | MIPS_CPU_COUNTER)
 
@@ -1172,7 +1470,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                        set_isa(c, MIPS_CPU_ISA_III);
                        c->fpu_msk31 |= FPU_CSR_CONDX;
                        break;
-               case PRID_REV_LOONGSON3A:
+               case PRID_REV_LOONGSON3A_R1:
                        c->cputype = CPU_LOONGSON3;
                        __cpu_name[cpu] = "ICT Loongson-3";
                        set_elf_platform(cpu, "loongson3a");
@@ -1314,6 +1612,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_P5600;
                __cpu_name[cpu] = "MIPS P5600";
                break;
+       case PRID_IMP_P6600:
+               c->cputype = CPU_P6600;
+               __cpu_name[cpu] = "MIPS P6600";
+               break;
        case PRID_IMP_I6400:
                c->cputype = CPU_I6400;
                __cpu_name[cpu] = "MIPS I6400";
@@ -1322,6 +1624,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_M5150;
                __cpu_name[cpu] = "MIPS M5150";
                break;
+       case PRID_IMP_M6250:
+               c->cputype = CPU_M6250;
+               __cpu_name[cpu] = "MIPS M6250";
+               break;
        }
 
        decode_configs(c);
@@ -1435,6 +1741,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
                        c->cputype = CPU_BMIPS4380;
                        __cpu_name[cpu] = "Broadcom BMIPS4380";
                        set_elf_platform(cpu, "bmips4380");
+                       c->options |= MIPS_CPU_RIXI;
                } else {
                        c->cputype = CPU_BMIPS4350;
                        __cpu_name[cpu] = "Broadcom BMIPS4350";
@@ -1445,9 +1752,12 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
        case PRID_IMP_BMIPS5000:
        case PRID_IMP_BMIPS5200:
                c->cputype = CPU_BMIPS5000;
-               __cpu_name[cpu] = "Broadcom BMIPS5000";
+               if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_BMIPS5200)
+                       __cpu_name[cpu] = "Broadcom BMIPS5200";
+               else
+                       __cpu_name[cpu] = "Broadcom BMIPS5000";
                set_elf_platform(cpu, "bmips5000");
-               c->options |= MIPS_CPU_ULRI;
+               c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI;
                break;
        }
 }
@@ -1481,6 +1791,8 @@ platform:
                set_elf_platform(cpu, "octeon2");
                break;
        case PRID_IMP_CAVIUM_CN70XX:
+       case PRID_IMP_CAVIUM_CN73XX:
+       case PRID_IMP_CAVIUM_CNF75XX:
        case PRID_IMP_CAVIUM_CN78XX:
                c->cputype = CPU_CAVIUM_OCTEON3;
                __cpu_name[cpu] = "Cavium Octeon III";
@@ -1493,6 +1805,29 @@ platform:
        }
 }
 
+static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
+{
+       switch (c->processor_id & PRID_IMP_MASK) {
+       case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
+               switch (c->processor_id & PRID_REV_MASK) {
+               case PRID_REV_LOONGSON3A_R2:
+                       c->cputype = CPU_LOONGSON3;
+                       __cpu_name[cpu] = "ICT Loongson-3";
+                       set_elf_platform(cpu, "loongson3a");
+                       set_isa(c, MIPS_CPU_ISA_M64R2);
+                       break;
+               }
+
+               decode_configs(c);
+               c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
+               c->writecombine = _CACHE_UNCACHED_ACCELERATED;
+               break;
+       default:
+               panic("Unknown Loongson Processor ID!");
+               break;
+       }
+}
+
 static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
@@ -1640,6 +1975,9 @@ void cpu_probe(void)
        case PRID_COMP_CAVIUM:
                cpu_probe_cavium(c, cpu);
                break;
+       case PRID_COMP_LOONGSON:
+               cpu_probe_loongson(c, cpu);
+               break;
        case PRID_COMP_INGENIC_D0:
        case PRID_COMP_INGENIC_D1:
        case PRID_COMP_INGENIC_E1:
@@ -1660,6 +1998,15 @@ void cpu_probe(void)
         */
        BUG_ON(current_cpu_type() != c->cputype);
 
+       if (cpu_has_rixi) {
+               /* Enable the RIXI exceptions */
+               set_c0_pagegrain(PG_IEC);
+               back_to_back_c0_hazard();
+               /* Verify the IEC bit is set */
+               if (read_c0_pagegrain() & PG_IEC)
+                       c->options |= MIPS_CPU_RIXIEX;
+       }
+
        if (mips_fpu_disabled)
                c->options &= ~MIPS_CPU_FPU;
 
@@ -1699,6 +2046,9 @@ void cpu_probe(void)
                elf_hwcap |= HWCAP_MIPS_MSA;
        }
 
+       if (cpu_has_vz)
+               cpu_probe_vz(c);
+
        cpu_probe_vmbits(c);
 
 #ifdef CONFIG_64BIT
index d434d5d5ae6e70b5241fe2fae2f3d1a0ec8bb1ed..610f0f3bdb3455cfa42629e98f8cc883524fe8ba 100644 (file)
@@ -14,12 +14,22 @@ static int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
 
 #ifdef CONFIG_SMP
-static void crash_shutdown_secondary(void *ignore)
+static void crash_shutdown_secondary(void *passed_regs)
 {
-       struct pt_regs *regs;
+       struct pt_regs *regs = passed_regs;
        int cpu = smp_processor_id();
 
-       regs = task_pt_regs(current);
+       /*
+        * If we are passed registers, use those.  Otherwise get the
+        * regs from the last interrupt, which should be correct, as
+        * we are in an interrupt.  But if the regs are not there,
+        * pull them from the top of the stack.  They are probably
+        * wrong, but we need something to keep from crashing again.
+        */
+       if (!regs)
+               regs = get_irq_regs();
+       if (!regs)
+               regs = task_pt_regs(current);
 
        if (!cpu_online(cpu))
                return;
index baa7b6fc0a60b1879976c2d4158f73d01e0ca53b..17326a90d53c7187111b8c5b0b15144844d0e07f 100644 (file)
@@ -130,7 +130,7 @@ LEAF(__r4k_wait)
        /* end of rollback region (the region size must be power of two) */
 1:
        jr      ra
-       nop
+        nop
        .set    pop
        END(__r4k_wait)
 
@@ -172,7 +172,7 @@ NESTED(handle_int, PT_SIZE, sp)
        mfc0    k0, CP0_EPC
        .set    noreorder
        j       k0
-       rfe
+        rfe
 #else
        and     k0, ST0_IE
        bnez    k0, 1f
@@ -189,7 +189,7 @@ NESTED(handle_int, PT_SIZE, sp)
        LONG_L  s0, TI_REGS($28)
        LONG_S  sp, TI_REGS($28)
        PTR_LA  ra, ret_from_irq
-       PTR_LA  v0, plat_irq_dispatch
+       PTR_LA  v0, plat_irq_dispatch
        jr      v0
 #ifdef CONFIG_CPU_MICROMIPS
        nop
@@ -292,7 +292,7 @@ ejtag_return:
        MFC0    k0, CP0_DESAVE
        .set    mips32
        deret
-       .set pop
+       .set    pop
        END(ejtag_debug_handler)
 
 /*
@@ -329,10 +329,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
         * Clear BEV - required for page fault exception handler to work
         */
        mfc0    k0, CP0_STATUS
-       ori     k0, k0, ST0_EXL
+       ori     k0, k0, ST0_EXL
        li      k1, ~(ST0_BEV | ST0_ERL)
-       and     k0, k0, k1
-       mtc0    k0, CP0_STATUS
+       and     k0, k0, k1
+       mtc0    k0, CP0_STATUS
        _ehb
        SAVE_ALL
        move    a0, sp
@@ -396,7 +396,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
 
        .macro  __BUILD_count exception
        LONG_L  t0,exception_count_\exception
-       LONG_ADDIU t0, 1
+       LONG_ADDIU      t0, 1
        LONG_S  t0,exception_count_\exception
        .comm   exception_count\exception, 8, 8
        .endm
@@ -455,10 +455,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    noreorder
        /* check if TLB contains a entry for EPC */
        MFC0    k1, CP0_ENTRYHI
-       andi    k1, 0xff        /* ASID_MASK */
+       andi    k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX
        MFC0    k0, CP0_EPC
-       PTR_SRL k0, _PAGE_SHIFT + 1
-       PTR_SLL k0, _PAGE_SHIFT + 1
+       PTR_SRL k0, _PAGE_SHIFT + 1
+       PTR_SLL k0, _PAGE_SHIFT + 1
        or      k1, k0
        MTC0    k1, CP0_ENTRYHI
        mtc0_tlbw_hazard
@@ -478,27 +478,27 @@ NESTED(nmi_handler, PT_SIZE, sp)
        /* microMIPS: 0x007d6b3c: rdhwr v1,$29 */
        MFC0    k1, CP0_EPC
 #if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2)
-       and     k0, k1, 1
-       beqz    k0, 1f
-       xor     k1, k0
-       lhu     k0, (k1)
-       lhu     k1, 2(k1)
-       ins     k1, k0, 16, 16
-       lui     k0, 0x007d
-       b       docheck
-       ori     k0, 0x6b3c
+       and     k0, k1, 1
+       beqz    k0, 1f
+        xor    k1, k0
+       lhu     k0, (k1)
+       lhu     k1, 2(k1)
+       ins     k1, k0, 16, 16
+       lui     k0, 0x007d
+       b       docheck
+        ori    k0, 0x6b3c
 1:
-       lui     k0, 0x7c03
-       lw      k1, (k1)
-       ori     k0, 0xe83b
+       lui     k0, 0x7c03
+       lw      k1, (k1)
+       ori     k0, 0xe83b
 #else
-       andi    k0, k1, 1
-       bnez    k0, handle_ri
-       lui     k0, 0x7c03
-       lw      k1, (k1)
-       ori     k0, 0xe83b
+       andi    k0, k1, 1
+       bnez    k0, handle_ri
+        lui    k0, 0x7c03
+       lw      k1, (k1)
+       ori     k0, 0xe83b
 #endif
-       .set    reorder
+       .set    reorder
 docheck:
        bne     k0, k1, handle_ri       /* if not ours */
 
index 4e4cc5b9a7714e78c8d4b3b5ac3f2c2eeba5c5c2..56e8fede3fd80504fa081dc1531235cad9f91f15 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/asmmacro.h>
 #include <asm/irqflags.h>
 #include <asm/regdef.h>
-#include <asm/pgtable-bits.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 
@@ -132,7 +131,27 @@ not_found:
        set_saved_sp    sp, t0, t1
        PTR_SUBU        sp, 4 * SZREG           # init stack pointer
 
+#ifdef CONFIG_RELOCATABLE
+       /* Copy kernel and apply the relocations */
+       jal             relocate_kernel
+
+       /* Repoint the sp into the new kernel image */
+       PTR_LI          sp, _THREAD_SIZE - 32 - PT_SIZE
+       PTR_ADDU        sp, $28
+       set_saved_sp    sp, t0, t1
+       PTR_SUBU        sp, 4 * SZREG           # init stack pointer
+
+       /*
+        * relocate_kernel returns the entry point either
+        * in the relocated kernel or the original if for
+        * some reason relocation failed - jump there now
+        * with instruction hazard barrier because of the
+        * newly sync'd icache.
+        */
+       jr.hb           v0
+#else
        j               start_kernel
+#endif
        END(kernel_entry)
 
 #ifdef CONFIG_SMP
index 46794d64c0bfe3f9779cc43714cc7c3fbb6a10bc..60ab4c44d30557b285a90cc28e7b8ae1dd2ca21a 100644 (file)
@@ -181,6 +181,11 @@ void __init check_wait(void)
        case CPU_XLP:
                cpu_wait = r4k_wait;
                break;
+       case CPU_LOONGSON3:
+               if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2)
+                       cpu_wait = r4k_wait;
+               break;
+
        case CPU_BMIPS5000:
                cpu_wait = r4k_wait_irqoff;
                break;
index 3fff89ae760bac4b2a49ecbcf3877948fd4f85c6..625ee770b1aa164d27cd2074ac3d1035420a8eed 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/inst.h>
 #include <asm/mips-r2-to-r6-emul.h>
 #include <asm/local.h>
+#include <asm/mipsregs.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
@@ -1251,10 +1252,10 @@ fpu_emul:
                        "       j       10b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word   1b,8b\n"
-                       "       .word   2b,8b\n"
-                       "       .word   3b,8b\n"
-                       "       .word   4b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -1326,10 +1327,10 @@ fpu_emul:
                        "       j       10b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word   1b,8b\n"
-                       "       .word   2b,8b\n"
-                       "       .word   3b,8b\n"
-                       "       .word   4b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -1397,10 +1398,10 @@ fpu_emul:
                        "       j       9b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word   1b,8b\n"
-                       "       .word   2b,8b\n"
-                       "       .word   3b,8b\n"
-                       "       .word   4b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -1467,10 +1468,10 @@ fpu_emul:
                        "       j       9b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word   1b,8b\n"
-                       "       .word   2b,8b\n"
-                       "       .word   3b,8b\n"
-                       "       .word   4b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -1582,14 +1583,14 @@ fpu_emul:
                        "       j       9b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word   1b,8b\n"
-                       "       .word   2b,8b\n"
-                       "       .word   3b,8b\n"
-                       "       .word   4b,8b\n"
-                       "       .word   5b,8b\n"
-                       "       .word   6b,8b\n"
-                       "       .word   7b,8b\n"
-                       "       .word   0b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
+                       STR(PTR) " 5b,8b\n"
+                       STR(PTR) " 6b,8b\n"
+                       STR(PTR) " 7b,8b\n"
+                       STR(PTR) " 0b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -1701,14 +1702,14 @@ fpu_emul:
                        "       j      9b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word  1b,8b\n"
-                       "       .word  2b,8b\n"
-                       "       .word  3b,8b\n"
-                       "       .word  4b,8b\n"
-                       "       .word  5b,8b\n"
-                       "       .word  6b,8b\n"
-                       "       .word  7b,8b\n"
-                       "       .word  0b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
+                       STR(PTR) " 5b,8b\n"
+                       STR(PTR) " 6b,8b\n"
+                       STR(PTR) " 7b,8b\n"
+                       STR(PTR) " 0b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -1820,14 +1821,14 @@ fpu_emul:
                        "       j       9b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word   1b,8b\n"
-                       "       .word   2b,8b\n"
-                       "       .word   3b,8b\n"
-                       "       .word   4b,8b\n"
-                       "       .word   5b,8b\n"
-                       "       .word   6b,8b\n"
-                       "       .word   7b,8b\n"
-                       "       .word   0b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
+                       STR(PTR) " 5b,8b\n"
+                       STR(PTR) " 6b,8b\n"
+                       STR(PTR) " 7b,8b\n"
+                       STR(PTR) " 0b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -1938,14 +1939,14 @@ fpu_emul:
                        "       j       9b\n"
                        "       .previous\n"
                        "       .section        __ex_table,\"a\"\n"
-                       "       .word   1b,8b\n"
-                       "       .word   2b,8b\n"
-                       "       .word   3b,8b\n"
-                       "       .word   4b,8b\n"
-                       "       .word   5b,8b\n"
-                       "       .word   6b,8b\n"
-                       "       .word   7b,8b\n"
-                       "       .word   0b,8b\n"
+                       STR(PTR) " 1b,8b\n"
+                       STR(PTR) " 2b,8b\n"
+                       STR(PTR) " 3b,8b\n"
+                       STR(PTR) " 4b,8b\n"
+                       STR(PTR) " 5b,8b\n"
+                       STR(PTR) " 6b,8b\n"
+                       STR(PTR) " 7b,8b\n"
+                       STR(PTR) " 0b,8b\n"
                        "       .previous\n"
                        "       .set    pop\n"
                        : "+&r"(rt), "=&r"(rs),
@@ -2000,7 +2001,7 @@ fpu_emul:
                        "j      2b\n"
                        ".previous\n"
                        ".section        __ex_table,\"a\"\n"
-                       ".word  1b, 3b\n"
+                       STR(PTR) " 1b,3b\n"
                        ".previous\n"
                        : "=&r"(res), "+&r"(err)
                        : "r"(vaddr), "i"(SIGSEGV)
@@ -2058,7 +2059,7 @@ fpu_emul:
                        "j      2b\n"
                        ".previous\n"
                        ".section        __ex_table,\"a\"\n"
-                       ".word  1b, 3b\n"
+                       STR(PTR) " 1b,3b\n"
                        ".previous\n"
                        : "+&r"(res), "+&r"(err)
                        : "r"(vaddr), "i"(SIGSEGV));
@@ -2119,7 +2120,7 @@ fpu_emul:
                        "j      2b\n"
                        ".previous\n"
                        ".section        __ex_table,\"a\"\n"
-                       ".word  1b, 3b\n"
+                       STR(PTR) " 1b,3b\n"
                        ".previous\n"
                        : "=&r"(res), "+&r"(err)
                        : "r"(vaddr), "i"(SIGSEGV)
@@ -2182,7 +2183,7 @@ fpu_emul:
                        "j      2b\n"
                        ".previous\n"
                        ".section        __ex_table,\"a\"\n"
-                       ".word  1b, 3b\n"
+                       STR(PTR) " 1b,3b\n"
                        ".previous\n"
                        : "+&r"(res), "+&r"(err)
                        : "r"(vaddr), "i"(SIGSEGV));
index 9083d63b765cf9532f3a7e42f892a3b90b50811a..7811688344565c013b917ddcb23d84609543c39f 100644 (file)
@@ -16,6 +16,7 @@
  *  Copyright (C) 2001 Rusty Russell.
  *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
  *  Copyright (C) 2005 Thiemo Seufer
+ *  Copyright (C) 2015 Imagination Technologies Ltd.
  */
 
 #include <linux/elf.h>
@@ -35,15 +36,13 @@ static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
 static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
 {
        if (v % 4) {
-               pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
+               pr_err("module %s: dangerous R_MIPS_26 RELA relocation\n",
                       me->name);
                return -ENOEXEC;
        }
 
        if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-               printk(KERN_ERR
-                      "module %s: relocation overflow\n",
-                      me->name);
+               pr_err("module %s: relocation overflow\n", me->name);
                return -ENOEXEC;
        }
 
@@ -67,6 +66,48 @@ static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v)
        return 0;
 }
 
+static int apply_r_mips_pc_rela(struct module *me, u32 *location, Elf_Addr v,
+                               unsigned bits)
+{
+       unsigned long mask = GENMASK(bits - 1, 0);
+       unsigned long se_bits;
+       long offset;
+
+       if (v % 4) {
+               pr_err("module %s: dangerous R_MIPS_PC%u RELA relocation\n",
+                      me->name, bits);
+               return -ENOEXEC;
+       }
+
+       offset = ((long)v - (long)location) >> 2;
+
+       /* check the sign bit onwards are identical - ie. we didn't overflow */
+       se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0;
+       if ((offset & ~mask) != (se_bits & ~mask)) {
+               pr_err("module %s: relocation overflow\n", me->name);
+               return -ENOEXEC;
+       }
+
+       *location = (*location & ~mask) | (offset & mask);
+
+       return 0;
+}
+
+static int apply_r_mips_pc16_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+       return apply_r_mips_pc_rela(me, location, v, 16);
+}
+
+static int apply_r_mips_pc21_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+       return apply_r_mips_pc_rela(me, location, v, 21);
+}
+
+static int apply_r_mips_pc26_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+       return apply_r_mips_pc_rela(me, location, v, 26);
+}
+
 static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
 {
        *(Elf_Addr *)location = v;
@@ -99,9 +140,12 @@ static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
        [R_MIPS_26]             = apply_r_mips_26_rela,
        [R_MIPS_HI16]           = apply_r_mips_hi16_rela,
        [R_MIPS_LO16]           = apply_r_mips_lo16_rela,
+       [R_MIPS_PC16]           = apply_r_mips_pc16_rela,
        [R_MIPS_64]             = apply_r_mips_64_rela,
        [R_MIPS_HIGHER]         = apply_r_mips_higher_rela,
-       [R_MIPS_HIGHEST]        = apply_r_mips_highest_rela
+       [R_MIPS_HIGHEST]        = apply_r_mips_highest_rela,
+       [R_MIPS_PC21_S2]        = apply_r_mips_pc21_rela,
+       [R_MIPS_PC26_S2]        = apply_r_mips_pc26_rela,
 };
 
 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
@@ -126,11 +170,11 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
                /* This is the symbol it is referring to */
                sym = (Elf_Sym *)sechdrs[symindex].sh_addr
                        + ELF_MIPS_R_SYM(rel[i]);
-               if (IS_ERR_VALUE(sym->st_value)) {
+               if (sym->st_value >= -MAX_ERRNO) {
                        /* Ignore unresolved weak symbol */
                        if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
                                continue;
-                       printk(KERN_WARNING "%s: Unknown symbol %s\n",
+                       pr_warn("%s: Unknown symbol %s\n",
                               me->name, strtab + sym->st_name);
                        return -ENOENT;
                }
index f9b2936d598def20f5f9be027a4b1e1a8af758c4..79850e376ef6387cb3956b9af78169fb12694bde 100644 (file)
@@ -73,8 +73,7 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
        }
 
        if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-               printk(KERN_ERR
-                      "module %s: relocation overflow\n",
+               pr_err("module %s: relocation overflow\n",
                       me->name);
                return -ENOEXEC;
        }
@@ -183,13 +182,62 @@ out_danger:
        return -ENOEXEC;
 }
 
+static int apply_r_mips_pc_rel(struct module *me, u32 *location, Elf_Addr v,
+                              unsigned bits)
+{
+       unsigned long mask = GENMASK(bits - 1, 0);
+       unsigned long se_bits;
+       long offset;
+
+       if (v % 4) {
+               pr_err("module %s: dangerous R_MIPS_PC%u REL relocation\n",
+                      me->name, bits);
+               return -ENOEXEC;
+       }
+
+       /* retrieve & sign extend implicit addend */
+       offset = *location & mask;
+       offset |= (offset & BIT(bits - 1)) ? ~mask : 0;
+
+       offset += ((long)v - (long)location) >> 2;
+
+       /* check the sign bit onwards are identical - ie. we didn't overflow */
+       se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0;
+       if ((offset & ~mask) != (se_bits & ~mask)) {
+               pr_err("module %s: relocation overflow\n", me->name);
+               return -ENOEXEC;
+       }
+
+       *location = (*location & ~mask) | (offset & mask);
+
+       return 0;
+}
+
+static int apply_r_mips_pc16_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+       return apply_r_mips_pc_rel(me, location, v, 16);
+}
+
+static int apply_r_mips_pc21_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+       return apply_r_mips_pc_rel(me, location, v, 21);
+}
+
+static int apply_r_mips_pc26_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+       return apply_r_mips_pc_rel(me, location, v, 26);
+}
+
 static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
                                Elf_Addr v) = {
        [R_MIPS_NONE]           = apply_r_mips_none,
        [R_MIPS_32]             = apply_r_mips_32_rel,
        [R_MIPS_26]             = apply_r_mips_26_rel,
        [R_MIPS_HI16]           = apply_r_mips_hi16_rel,
-       [R_MIPS_LO16]           = apply_r_mips_lo16_rel
+       [R_MIPS_LO16]           = apply_r_mips_lo16_rel,
+       [R_MIPS_PC16]           = apply_r_mips_pc16_rel,
+       [R_MIPS_PC21_S2]        = apply_r_mips_pc21_rel,
+       [R_MIPS_PC26_S2]        = apply_r_mips_pc26_rel,
 };
 
 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
@@ -215,12 +263,12 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
                /* This is the symbol it is referring to */
                sym = (Elf_Sym *)sechdrs[symindex].sh_addr
                        + ELF_MIPS_R_SYM(rel[i]);
-               if (IS_ERR_VALUE(sym->st_value)) {
+               if (sym->st_value >= -MAX_ERRNO) {
                        /* Ignore unresolved weak symbol */
                        if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
                                continue;
-                       printk(KERN_WARNING "%s: Unknown symbol %s\n",
-                              me->name, strtab + sym->st_name);
+                       pr_warn("%s: Unknown symbol %s\n",
+                               me->name, strtab + sym->st_name);
                        return -ENOENT;
                }
 
index 9bc1191b1ab0d32c05d7f7d15e2a6e4995262933..d3ba9f4105b557d76cf3bf5000d7dcfb074b5ec7 100644 (file)
@@ -101,8 +101,6 @@ struct mips_pmu {
 
 static struct mips_pmu mipspmu;
 
-#define M_CONFIG1_PC   (1 << 4)
-
 #define M_PERFCTL_EXL                  (1      <<  0)
 #define M_PERFCTL_KERNEL               (1      <<  1)
 #define M_PERFCTL_SUPERVISOR           (1      <<  2)
@@ -754,7 +752,7 @@ static void handle_associated_event(struct cpu_hw_events *cpuc,
 
 static int __n_counters(void)
 {
-       if (!(read_c0_config1() & M_CONFIG1_PC))
+       if (!cpu_has_perf)
                return 0;
        if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
                return 1;
@@ -825,6 +823,16 @@ static const struct mips_perf_event mipsxxcore_event_map2
        [PERF_COUNT_HW_BRANCH_MISSES] = { 0x27, CNTR_ODD, T },
 };
 
+static const struct mips_perf_event i6400_event_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]          = { 0x00, CNTR_EVEN | CNTR_ODD },
+       [PERF_COUNT_HW_INSTRUCTIONS]        = { 0x01, CNTR_EVEN | CNTR_ODD },
+       /* These only count dcache, not icache */
+       [PERF_COUNT_HW_CACHE_REFERENCES]    = { 0x45, CNTR_EVEN | CNTR_ODD },
+       [PERF_COUNT_HW_CACHE_MISSES]        = { 0x48, CNTR_EVEN | CNTR_ODD },
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x15, CNTR_EVEN | CNTR_ODD },
+       [PERF_COUNT_HW_BRANCH_MISSES]       = { 0x16, CNTR_EVEN | CNTR_ODD },
+};
+
 static const struct mips_perf_event loongson3_event_map[PERF_COUNT_HW_MAX] = {
        [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN },
        [PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, CNTR_ODD },
@@ -1015,6 +1023,46 @@ static const struct mips_perf_event mipsxxcore_cache_map2
 },
 };
 
+static const struct mips_perf_event i6400_cache_map
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x46, CNTR_EVEN | CNTR_ODD },
+               [C(RESULT_MISS)]        = { 0x49, CNTR_EVEN | CNTR_ODD },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { 0x47, CNTR_EVEN | CNTR_ODD },
+               [C(RESULT_MISS)]        = { 0x4a, CNTR_EVEN | CNTR_ODD },
+       },
+},
+[C(L1I)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x84, CNTR_EVEN | CNTR_ODD },
+               [C(RESULT_MISS)]        = { 0x85, CNTR_EVEN | CNTR_ODD },
+       },
+},
+[C(DTLB)] = {
+       /* Can't distinguish read & write */
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x40, CNTR_EVEN | CNTR_ODD },
+               [C(RESULT_MISS)]        = { 0x41, CNTR_EVEN | CNTR_ODD },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { 0x40, CNTR_EVEN | CNTR_ODD },
+               [C(RESULT_MISS)]        = { 0x41, CNTR_EVEN | CNTR_ODD },
+       },
+},
+[C(BPU)] = {
+       /* Conditional branches / mispredicted */
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x15, CNTR_EVEN | CNTR_ODD },
+               [C(RESULT_MISS)]        = { 0x16, CNTR_EVEN | CNTR_ODD },
+       },
+},
+};
+
 static const struct mips_perf_event loongson3_cache_map
                                [PERF_COUNT_HW_CACHE_MAX]
                                [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -1556,6 +1604,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 #endif
                break;
        case CPU_P5600:
+       case CPU_P6600:
        case CPU_I6400:
                /* 8-bit event numbers */
                raw_id = config & 0x1ff;
@@ -1718,11 +1767,16 @@ init_hw_perf_events(void)
                mipspmu.general_event_map = &mipsxxcore_event_map2;
                mipspmu.cache_event_map = &mipsxxcore_cache_map2;
                break;
-       case CPU_I6400:
-               mipspmu.name = "mips/I6400";
+       case CPU_P6600:
+               mipspmu.name = "mips/P6600";
                mipspmu.general_event_map = &mipsxxcore_event_map2;
                mipspmu.cache_event_map = &mipsxxcore_cache_map2;
                break;
+       case CPU_I6400:
+               mipspmu.name = "mips/I6400";
+               mipspmu.general_event_map = &i6400_event_map;
+               mipspmu.cache_event_map = &i6400_cache_map;
+               break;
        case CPU_1004K:
                mipspmu.name = "mips/1004K";
                mipspmu.general_event_map = &mipsxxcore_event_map;
index fa3f9ebad8f40503ccd6622c8c91c56c6e6188ee..adda3ffb9b78f74717f34ff0d8667aed18b537a0 100644 (file)
@@ -224,11 +224,18 @@ static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl,
        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);
+       for (i = 0; i < unroll_lines; i++) {
+               if (cpu_has_mips_r6) {
+                       uasm_i_cache(pp, op, 0, t0);
+                       uasm_i_addiu(pp, t0, t0, cache->linesz);
+               } else {
+                       uasm_i_cache(pp, op, i * cache->linesz, t0);
+               }
+       }
 
-       /* Update the base address */
-       uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz);
+       if (!cpu_has_mips_r6)
+               /* 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);
index fefdf39d3df352ebb68e309607398e72f76f3611..dc814892133c0f7f7c71728cf0eeadad19295ae8 100644 (file)
@@ -56,7 +56,7 @@ static void mips_cpu_restore(void)
                write_c0_userlocal(current_thread_info()->tp_value);
 
        /* Restore watch registers */
-       __restore_watch();
+       __restore_watch(current);
 }
 
 /**
index 298b2b773d12ba8f875d2d0e253ba19a60f93e2c..97dc01b03631196252c118f592e58e7b41bca428 100644 (file)
@@ -114,6 +114,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        if (cpu_has_smartmips)  seq_printf(m, "%s", " smartmips");
        if (cpu_has_dsp)        seq_printf(m, "%s", " dsp");
        if (cpu_has_dsp2)       seq_printf(m, "%s", " dsp2");
+       if (cpu_has_dsp3)       seq_printf(m, "%s", " dsp3");
        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");
index 92880cee449e147043f4007204f286b6cd869f88..a6b3dc54260a51cd06e28777f770f1c3cfd74911 100644 (file)
@@ -77,10 +77,6 @@ void exit_thread(void)
 {
 }
 
-void flush_thread(void)
-{
-}
-
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
        /*
@@ -455,7 +451,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page,
                    *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) {
                        regs = (struct pt_regs *)*sp;
                        pc = regs->cp0_epc;
-                       if (__kernel_text_address(pc)) {
+                       if (!user_mode(regs) && __kernel_text_address(pc)) {
                                *sp = regs->regs[29];
                                *ra = regs->regs[31];
                                return pc;
@@ -580,11 +576,19 @@ int mips_get_process_fp_mode(struct task_struct *task)
        return value;
 }
 
+static void prepare_for_fp_mode_switch(void *info)
+{
+       struct mm_struct *mm = info;
+
+       if (current->mm == mm)
+               lose_fpu(1);
+}
+
 int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 {
        const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
-       unsigned long switch_count;
        struct task_struct *t;
+       int max_users;
 
        /* Check the value is valid */
        if (value & ~known_bits)
@@ -601,6 +605,9 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
        if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
                return -EOPNOTSUPP;
 
+       /* Proceed with the mode switch */
+       preempt_disable();
+
        /* Save FP & vector context, then disable FPU & MSA */
        if (task->signal == current->signal)
                lose_fpu(1);
@@ -610,31 +617,17 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
        smp_mb__after_atomic();
 
        /*
-        * If there are multiple online CPUs then wait until all threads whose
-        * FP mode is about to change have been context switched. This approach
-        * allows us to only worry about whether an FP mode switch is in
-        * progress when FP is first used in a tasks time slice. Pretty much all
-        * of the mode switch overhead can thus be confined to cases where mode
-        * switches are actually occurring. That is, to here. However for the
-        * thread performing the mode switch it may take a while...
+        * If there are multiple online CPUs then force any which are running
+        * threads in this process to lose their FPU context, which they can't
+        * regain until fp_mode_switching is cleared later.
         */
        if (num_online_cpus() > 1) {
-               spin_lock_irq(&task->sighand->siglock);
-
-               for_each_thread(task, t) {
-                       if (t == current)
-                               continue;
-
-                       switch_count = t->nvcsw + t->nivcsw;
+               /* No need to send an IPI for the local CPU */
+               max_users = (task->mm == current->mm) ? 1 : 0;
 
-                       do {
-                               spin_unlock_irq(&task->sighand->siglock);
-                               cond_resched();
-                               spin_lock_irq(&task->sighand->siglock);
-                       } while ((t->nvcsw + t->nivcsw) == switch_count);
-               }
-
-               spin_unlock_irq(&task->sighand->siglock);
+               if (atomic_read(&current->mm->mm_users) > max_users)
+                       smp_call_function(prepare_for_fp_mode_switch,
+                                         (void *)current->mm, 1);
        }
 
        /*
@@ -659,6 +652,7 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 
        /* Allow threads to use FP again */
        atomic_set(&task->mm->context.fp_mode_switching, 0);
+       preempt_enable();
 
        return 0;
 }
index a5279b2f31989f8c8dcd915fccb233a4ada33332..0dcf69194473c6469cbd8ce6cdcdb06499f3b483 100644 (file)
@@ -57,8 +57,7 @@ static void init_fp_ctx(struct task_struct *target)
        /* Begin with data registers set to all 1s... */
        memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
 
-       /* ...and FCSR zeroed */
-       target->thread.fpu.fcr31 = 0;
+       /* FCSR has been preset by `mips_set_personality_nan'.  */
 
        /*
         * Record that the target has "used" math, such that the context
@@ -79,6 +78,22 @@ void ptrace_disable(struct task_struct *child)
        clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
 }
 
+/*
+ * Poke at FCSR according to its mask.  Don't set the cause bits as
+ * this is currently not handled correctly in FP context restoration
+ * and will cause an oops if a corresponding enable bit is set.
+ */
+static void ptrace_setfcr31(struct task_struct *child, u32 value)
+{
+       u32 fcr31;
+       u32 mask;
+
+       value &= ~FPU_CSR_ALL_X;
+       fcr31 = child->thread.fpu.fcr31;
+       mask = boot_cpu_data.fpu_msk31;
+       child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+}
+
 /*
  * Read a general register set.         We always use the 64-bit format, even
  * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
@@ -159,9 +174,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
 {
        union fpureg *fregs;
        u64 fpr_val;
-       u32 fcr31;
        u32 value;
-       u32 mask;
        int i;
 
        if (!access_ok(VERIFY_READ, data, 33 * 8))
@@ -176,9 +189,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
        }
 
        __get_user(value, data + 64);
-       fcr31 = child->thread.fpu.fcr31;
-       mask = boot_cpu_data.fpu_msk31;
-       child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+       ptrace_setfcr31(child, value);
 
        /* FIR may not be written.  */
 
@@ -210,7 +221,8 @@ int ptrace_get_watch_regs(struct task_struct *child,
        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,
+               __put_user(child->thread.watch.mips3264.watchhi[i] &
+                               (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW),
                           &addr->WATCH_STYLE.watchhi[i]);
                __put_user(boot_cpu_data.watch_reg_masks[i],
                           &addr->WATCH_STYLE.watch_masks[i]);
@@ -252,12 +264,12 @@ int ptrace_set_watch_regs(struct task_struct *child,
                }
 #endif
                __get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]);
-               if (ht[i] & ~0xff8)
+               if (ht[i] & ~MIPS_WATCHHI_MASK)
                        return -EINVAL;
        }
        /* Install them. */
        for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
-               if (lt[i] & 7)
+               if (lt[i] & MIPS_WATCHLO_IRW)
                        watch_active = 1;
                child->thread.watch.mips3264.watchlo[i] = lt[i];
                /* Set the G bit. */
@@ -805,7 +817,7 @@ long arch_ptrace(struct task_struct *child, long request,
                        break;
 #endif
                case FPC_CSR:
-                       child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
+                       ptrace_setfcr31(child, data);
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
index 17732f876eff1ad7e7e868f960304420e380db93..56d86b09c917b0de80efca96ac357ef3e8a63c7e 100644 (file)
@@ -244,17 +244,17 @@ LEAF(\name)
        .set    push
        .set    noat
 #ifdef CONFIG_64BIT
-       copy_u_d \wr, 1
+       copy_s_d \wr, 1
        EX sd   $1, \off(\base)
 #elif defined(CONFIG_CPU_LITTLE_ENDIAN)
-       copy_u_w \wr, 2
+       copy_s_w \wr, 2
        EX sw   $1, \off(\base)
-       copy_u_w \wr, 3
+       copy_s_w \wr, 3
        EX sw   $1, (\off+4)(\base)
 #else /* CONFIG_CPU_BIG_ENDIAN */
-       copy_u_w \wr, 2
+       copy_s_w \wr, 2
        EX sw   $1, (\off+4)(\base)
-       copy_u_w \wr, 3
+       copy_s_w \wr, 3
        EX sw   $1, \off(\base)
 #endif
        .set    pop
index 92cd0516ecf51ee40715824b26ab48be8146cce8..2f0a3b223c97b11276492e4d763a8a5c00a75d0f 100644 (file)
@@ -15,7 +15,6 @@
 #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>
diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c
new file mode 100644 (file)
index 0000000..ca1cc30
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * 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.
+ *
+ * Support for Kernel relocation at boot time
+ *
+ * Copyright (C) 2015, Imagination Technologies Ltd.
+ * Authors: Matt Redfearn (matt.redfearn@imgtec.com)
+ */
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/fw/fw.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/timex.h>
+#include <linux/elf.h>
+#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/sched.h>
+#include <linux/start_kernel.h>
+#include <linux/string.h>
+#include <linux/printk.h>
+
+#define RELOCATED(x) ((void *)((long)x + offset))
+
+extern u32 _relocation_start[];        /* End kernel image / start relocation table */
+extern u32 _relocation_end[];  /* End relocation table */
+
+extern long __start___ex_table;        /* Start exception table */
+extern long __stop___ex_table; /* End exception table */
+
+static inline u32 __init get_synci_step(void)
+{
+       u32 res;
+
+       __asm__("rdhwr  %0, $1" : "=r" (res));
+
+       return res;
+}
+
+static void __init sync_icache(void *kbase, unsigned long kernel_length)
+{
+       void *kend = kbase + kernel_length;
+       u32 step = get_synci_step();
+
+       do {
+               __asm__ __volatile__(
+                       "synci  0(%0)"
+                       : /* no output */
+                       : "r" (kbase));
+
+               kbase += step;
+       } while (kbase < kend);
+
+       /* Completion barrier */
+       __sync();
+}
+
+static int __init apply_r_mips_64_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+       *(u64 *)loc_new += offset;
+
+       return 0;
+}
+
+static int __init apply_r_mips_32_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+       *loc_new += offset;
+
+       return 0;
+}
+
+static int __init apply_r_mips_26_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+       unsigned long target_addr = (*loc_orig) & 0x03ffffff;
+
+       if (offset % 4) {
+               pr_err("Dangerous R_MIPS_26 REL relocation\n");
+               return -ENOEXEC;
+       }
+
+       /* Original target address */
+       target_addr <<= 2;
+       target_addr += (unsigned long)loc_orig & ~0x03ffffff;
+
+       /* Get the new target address */
+       target_addr += offset;
+
+       if ((target_addr & 0xf0000000) != ((unsigned long)loc_new & 0xf0000000)) {
+               pr_err("R_MIPS_26 REL relocation overflow\n");
+               return -ENOEXEC;
+       }
+
+       target_addr -= (unsigned long)loc_new & ~0x03ffffff;
+       target_addr >>= 2;
+
+       *loc_new = (*loc_new & ~0x03ffffff) | (target_addr & 0x03ffffff);
+
+       return 0;
+}
+
+
+static int __init apply_r_mips_hi16_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+       unsigned long insn = *loc_orig;
+       unsigned long target = (insn & 0xffff) << 16; /* high 16bits of target */
+
+       target += offset;
+
+       *loc_new = (insn & ~0xffff) | ((target >> 16) & 0xffff);
+       return 0;
+}
+
+static int (*reloc_handlers_rel[]) (u32 *, u32 *, long) __initdata = {
+       [R_MIPS_64]             = apply_r_mips_64_rel,
+       [R_MIPS_32]             = apply_r_mips_32_rel,
+       [R_MIPS_26]             = apply_r_mips_26_rel,
+       [R_MIPS_HI16]           = apply_r_mips_hi16_rel,
+};
+
+int __init do_relocations(void *kbase_old, void *kbase_new, long offset)
+{
+       u32 *r;
+       u32 *loc_orig;
+       u32 *loc_new;
+       int type;
+       int res;
+
+       for (r = _relocation_start; r < _relocation_end; r++) {
+               /* Sentinel for last relocation */
+               if (*r == 0)
+                       break;
+
+               type = (*r >> 24) & 0xff;
+               loc_orig = (void *)(kbase_old + ((*r & 0x00ffffff) << 2));
+               loc_new = RELOCATED(loc_orig);
+
+               if (reloc_handlers_rel[type] == NULL) {
+                       /* Unsupported relocation */
+                       pr_err("Unhandled relocation type %d at 0x%pK\n",
+                              type, loc_orig);
+                       return -ENOEXEC;
+               }
+
+               res = reloc_handlers_rel[type](loc_orig, loc_new, offset);
+               if (res)
+                       return res;
+       }
+
+       return 0;
+}
+
+/*
+ * The exception table is filled in by the relocs tool after vmlinux is linked.
+ * It must be relocated separately since there will not be any relocation
+ * information for it filled in by the linker.
+ */
+static int __init relocate_exception_table(long offset)
+{
+       unsigned long *etable_start, *etable_end, *e;
+
+       etable_start = RELOCATED(&__start___ex_table);
+       etable_end = RELOCATED(&__stop___ex_table);
+
+       for (e = etable_start; e < etable_end; e++)
+               *e += offset;
+
+       return 0;
+}
+
+#ifdef CONFIG_RANDOMIZE_BASE
+
+static inline __init unsigned long rotate_xor(unsigned long hash,
+                                             const void *area, size_t size)
+{
+       size_t i;
+       unsigned long *ptr = (unsigned long *)area;
+
+       for (i = 0; i < size / sizeof(hash); i++) {
+               /* Rotate by odd number of bits and XOR. */
+               hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
+               hash ^= ptr[i];
+       }
+
+       return hash;
+}
+
+static inline __init unsigned long get_random_boot(void)
+{
+       unsigned long entropy = random_get_entropy();
+       unsigned long hash = 0;
+
+       /* Attempt to create a simple but unpredictable starting entropy. */
+       hash = rotate_xor(hash, linux_banner, strlen(linux_banner));
+
+       /* Add in any runtime entropy we can get */
+       hash = rotate_xor(hash, &entropy, sizeof(entropy));
+
+#if defined(CONFIG_USE_OF)
+       /* Get any additional entropy passed in device tree */
+       {
+               int node, len;
+               u64 *prop;
+
+               node = fdt_path_offset(initial_boot_params, "/chosen");
+               if (node >= 0) {
+                       prop = fdt_getprop_w(initial_boot_params, node,
+                                            "kaslr-seed", &len);
+                       if (prop && (len == sizeof(u64)))
+                               hash = rotate_xor(hash, prop, sizeof(*prop));
+               }
+       }
+#endif /* CONFIG_USE_OF */
+
+       return hash;
+}
+
+static inline __init bool kaslr_disabled(void)
+{
+       char *str;
+
+#if defined(CONFIG_CMDLINE_BOOL)
+       const char *builtin_cmdline = CONFIG_CMDLINE;
+
+       str = strstr(builtin_cmdline, "nokaslr");
+       if (str == builtin_cmdline ||
+           (str > builtin_cmdline && *(str - 1) == ' '))
+               return true;
+#endif
+       str = strstr(arcs_cmdline, "nokaslr");
+       if (str == arcs_cmdline || (str > arcs_cmdline && *(str - 1) == ' '))
+               return true;
+
+       return false;
+}
+
+static inline void __init *determine_relocation_address(void)
+{
+       /* Choose a new address for the kernel */
+       unsigned long kernel_length;
+       void *dest = &_text;
+       unsigned long offset;
+
+       if (kaslr_disabled())
+               return dest;
+
+       kernel_length = (long)_end - (long)(&_text);
+
+       offset = get_random_boot() << 16;
+       offset &= (CONFIG_RANDOMIZE_BASE_MAX_OFFSET - 1);
+       if (offset < kernel_length)
+               offset += ALIGN(kernel_length, 0xffff);
+
+       return RELOCATED(dest);
+}
+
+#else
+
+static inline void __init *determine_relocation_address(void)
+{
+       /*
+        * Choose a new address for the kernel
+        * For now we'll hard code the destination
+        */
+       return (void *)0xffffffff81000000;
+}
+
+#endif
+
+static inline int __init relocation_addr_valid(void *loc_new)
+{
+       if ((unsigned long)loc_new & 0x0000ffff) {
+               /* Inappropriately aligned new location */
+               return 0;
+       }
+       if ((unsigned long)loc_new < (unsigned long)&_end) {
+               /* New location overlaps original kernel */
+               return 0;
+       }
+       return 1;
+}
+
+void *__init relocate_kernel(void)
+{
+       void *loc_new;
+       unsigned long kernel_length;
+       unsigned long bss_length;
+       long offset = 0;
+       int res = 1;
+       /* Default to original kernel entry point */
+       void *kernel_entry = start_kernel;
+
+       /* Get the command line */
+       fw_init_cmdline();
+#if defined(CONFIG_USE_OF)
+       /* Deal with the device tree */
+       early_init_dt_scan(plat_get_fdt());
+       if (boot_command_line[0]) {
+               /* Boot command line was passed in device tree */
+               strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+       }
+#endif /* CONFIG_USE_OF */
+
+       kernel_length = (long)(&_relocation_start) - (long)(&_text);
+       bss_length = (long)&__bss_stop - (long)&__bss_start;
+
+       loc_new = determine_relocation_address();
+
+       /* Sanity check relocation address */
+       if (relocation_addr_valid(loc_new))
+               offset = (unsigned long)loc_new - (unsigned long)(&_text);
+
+       /* Reset the command line now so we don't end up with a duplicate */
+       arcs_cmdline[0] = '\0';
+
+       if (offset) {
+               /* Copy the kernel to it's new location */
+               memcpy(loc_new, &_text, kernel_length);
+
+               /* Perform relocations on the new kernel */
+               res = do_relocations(&_text, loc_new, offset);
+               if (res < 0)
+                       goto out;
+
+               /* Sync the caches ready for execution of new kernel */
+               sync_icache(loc_new, kernel_length);
+
+               res = relocate_exception_table(offset);
+               if (res < 0)
+                       goto out;
+
+               /*
+                * The original .bss has already been cleared, and
+                * some variables such as command line parameters
+                * stored to it so make a copy in the new location.
+                */
+               memcpy(RELOCATED(&__bss_start), &__bss_start, bss_length);
+
+               /* The current thread is now within the relocated image */
+               __current_thread_info = RELOCATED(&init_thread_union);
+
+               /* Return the new kernel's entry point */
+               kernel_entry = RELOCATED(start_kernel);
+       }
+out:
+       return kernel_entry;
+}
+
+/*
+ * Show relocation information on panic.
+ */
+void show_kernel_relocation(const char *level)
+{
+       unsigned long offset;
+
+       offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS);
+
+       if (IS_ENABLED(CONFIG_RELOCATABLE) && offset > 0) {
+               printk(level);
+               pr_cont("Kernel relocated by 0x%pK\n", (void *)offset);
+               pr_cont(" .text @ 0x%pK\n", _text);
+               pr_cont(" .data @ 0x%pK\n", _sdata);
+               pr_cont(" .bss  @ 0x%pK\n", __bss_start);
+       }
+}
+
+static int kernel_location_notifier_fn(struct notifier_block *self,
+                                      unsigned long v, void *p)
+{
+       show_kernel_relocation(KERN_EMERG);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block kernel_location_notifier = {
+       .notifier_call = kernel_location_notifier_fn
+};
+
+static int __init register_kernel_offset_dumper(void)
+{
+       atomic_notifier_chain_register(&panic_notifier_list,
+                                      &kernel_location_notifier);
+       return 0;
+}
+__initcall(register_kernel_offset_dumper);
index d01fe53a663850bccbea14e30208357df5aa074b..c8e43e0c4066b599fd24b1135eebac0129252d17 100644 (file)
@@ -35,7 +35,6 @@ NESTED(handle_sys, PT_SIZE, sp)
 
        lw      t1, PT_EPC(sp)          # skip syscall on return
 
-       subu    v0, v0, __NR_O32_Linux  # check syscall number
        addiu   t1, 4                   # skip to next instruction
        sw      t1, PT_EPC(sp)
 
@@ -89,6 +88,7 @@ loads_done:
        and     t0, t1
        bnez    t0, syscall_trace_entry # -> yes
 syscall_common:
+       subu    v0, v0, __NR_O32_Linux  # check syscall number
        sltiu   t0, v0, __NR_O32_Linux_syscalls + 1
        beqz    t0, illegal_syscall
 
@@ -118,24 +118,23 @@ o32_syscall_exit:
 
 syscall_trace_entry:
        SAVE_STATIC
-       move    s0, v0
        move    a0, sp
 
        /*
         * 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 */
+       move    a1, v0
+       subu    t2, v0,  __NR_O32_Linux
+       bnez    t2, 1f /* __NR_syscall at offset 0 */
        lw      a1, PT_R4(sp)
 
 1:     jal     syscall_trace_enter
 
        bltz    v0, 1f                  # seccomp failed? Skip syscall
 
-       move    v0, s0                  # restore syscall
-
        RESTORE_STATIC
+       lw      v0, PT_R2(sp)           # Restore syscall (maybe modified)
        lw      a0, PT_R4(sp)           # Restore argument registers
        lw      a1, PT_R5(sp)
        lw      a2, PT_R6(sp)
index 6b73ecc02597c008c0025a89b4ebf252f73c8a38..e6ede125059fe87253edb0bd5a5d9e46c8ef0fff 100644 (file)
@@ -82,15 +82,14 @@ n64_syscall_exit:
 
 syscall_trace_entry:
        SAVE_STATIC
-       move    s0, v0
        move    a0, sp
        move    a1, v0
        jal     syscall_trace_enter
 
        bltz    v0, 1f                  # seccomp failed? Skip syscall
 
-       move    v0, s0
        RESTORE_STATIC
+       ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
        ld      a0, PT_R4(sp)           # Restore argument registers
        ld      a1, PT_R5(sp)
        ld      a2, PT_R6(sp)
index 71f99d5f7a068220c17c9ab4da4cd6419f356b67..9c0b387d6427b1f06d2cd15f3d4e6e9444389fb9 100644 (file)
@@ -42,9 +42,6 @@ NESTED(handle_sysn32, PT_SIZE, sp)
 #endif
        beqz    t0, not_n32_scall
 
-       dsll    t0, v0, 3               # offset into table
-       ld      t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
-
        sd      a3, PT_R26(sp)          # save a3 for syscall restarting
 
        li      t1, _TIF_WORK_SYSCALL_ENTRY
@@ -53,6 +50,9 @@ NESTED(handle_sysn32, PT_SIZE, sp)
        bnez    t0, n32_syscall_trace_entry
 
 syscall_common:
+       dsll    t0, v0, 3               # offset into table
+       ld      t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
+
        jalr    t2                      # Do The Real Thing (TM)
 
        li      t0, -EMAXERRNO - 1      # error?
@@ -71,21 +71,25 @@ syscall_common:
 
 n32_syscall_trace_entry:
        SAVE_STATIC
-       move    s0, t2
        move    a0, sp
        move    a1, v0
        jal     syscall_trace_enter
 
        bltz    v0, 1f                  # seccomp failed? Skip syscall
 
-       move    t2, s0
        RESTORE_STATIC
+       ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
        ld      a0, PT_R4(sp)           # Restore argument registers
        ld      a1, PT_R5(sp)
        ld      a2, PT_R6(sp)
        ld      a3, PT_R7(sp)
        ld      a4, PT_R8(sp)
        ld      a5, PT_R9(sp)
+
+       dsubu   t2, v0, __NR_N32_Linux  # check (new) syscall number
+       sltiu   t0, t2, __NR_N32_Linux_syscalls + 1
+       beqz    t0, not_n32_scall
+
        j       syscall_common
 
 1:     j       syscall_exit
index 91b43eea2d5a073026ef8f4928d74e41ca0bfb07..f4f28b1580ded57d4dc5b0a7e49e289004680590 100644 (file)
@@ -52,9 +52,6 @@ NESTED(handle_sys, PT_SIZE, sp)
        sll     a2, a2, 0
        sll     a3, a3, 0
 
-       dsll    t0, v0, 3               # offset into table
-       ld      t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
-
        sd      a3, PT_R26(sp)          # save a3 for syscall restarting
 
        /*
@@ -88,6 +85,9 @@ loads_done:
        bnez    t0, trace_a_syscall
 
 syscall_common:
+       dsll    t0, v0, 3               # offset into table
+       ld      t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
+
        jalr    t2                      # Do The Real Thing (TM)
 
        li      t0, -EMAXERRNO - 1      # error?
@@ -112,7 +112,6 @@ trace_a_syscall:
        sd      a6, PT_R10(sp)
        sd      a7, PT_R11(sp)          # For indirect syscalls
 
-       move    s0, t2                  # Save syscall pointer
        move    a0, sp
        /*
         * absolute syscall number is in v0 unless we called syscall(__NR_###)
@@ -133,8 +132,8 @@ trace_a_syscall:
 
        bltz    v0, 1f                  # seccomp failed? Skip syscall
 
-       move    t2, s0
        RESTORE_STATIC
+       ld      v0, PT_R2(sp)           # Restore syscall (maybe modified)
        ld      a0, PT_R4(sp)           # Restore argument registers
        ld      a1, PT_R5(sp)
        ld      a2, PT_R6(sp)
@@ -143,6 +142,11 @@ trace_a_syscall:
        ld      a5, PT_R9(sp)
        ld      a6, PT_R10(sp)
        ld      a7, PT_R11(sp)          # For indirect syscalls
+
+       dsubu   t0, v0, __NR_O32_Linux  # check (new) syscall number
+       sltiu   t0, t0, __NR_O32_Linux_syscalls + 1
+       beqz    t0, not_o32_scall
+
        j       syscall_common
 
 1:     j       syscall_exit
index 4f607341a7938867efc6f0f0646c218bf168421b..ef408a03e818860bf18dc95ed08adb3084892401 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/sizes.h>
 #include <linux/device.h>
 #include <linux/dma-contiguous.h>
+#include <linux/decompress/generic.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -51,13 +52,6 @@ EXPORT_SYMBOL(cpu_data);
 struct screen_info screen_info;
 #endif
 
-/*
- * Despite it's name this variable is even if we don't have PCI
- */
-unsigned int PCI_DMA_BUS_IS_PHYS;
-
-EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
-
 /*
  * Setup information
  *
@@ -250,6 +244,35 @@ disable:
        return 0;
 }
 
+/* In some conditions (e.g. big endian bootloader with a little endian
+   kernel), the initrd might appear byte swapped.  Try to detect this and
+   byte swap it if needed.  */
+static void __init maybe_bswap_initrd(void)
+{
+#if defined(CONFIG_CPU_CAVIUM_OCTEON)
+       u64 buf;
+
+       /* Check for CPIO signature */
+       if (!memcmp((void *)initrd_start, "070701", 6))
+               return;
+
+       /* Check for compressed initrd */
+       if (decompress_method((unsigned char *)initrd_start, 8, NULL))
+               return;
+
+       /* Try again with a byte swapped header */
+       buf = swab64p((u64 *)initrd_start);
+       if (!memcmp(&buf, "070701", 6) ||
+           decompress_method((unsigned char *)(&buf), 8, NULL)) {
+               unsigned long i;
+
+               pr_info("Byteswapped initrd detected\n");
+               for (i = initrd_start; i < ALIGN(initrd_end, 8); i += 8)
+                       swab64s((u64 *)i);
+       }
+#endif
+}
+
 static void __init finalize_initrd(void)
 {
        unsigned long size = initrd_end - initrd_start;
@@ -263,6 +286,8 @@ static void __init finalize_initrd(void)
                goto disable;
        }
 
+       maybe_bswap_initrd();
+
        reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT);
        initrd_below_start_ok = 1;
 
@@ -469,6 +494,29 @@ static void __init bootmem_init(void)
         */
        reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT);
 
+#ifdef CONFIG_RELOCATABLE
+       /*
+        * The kernel reserves all memory below its _end symbol as bootmem,
+        * but the kernel may now be at a much higher address. The memory
+        * between the original and new locations may be returned to the system.
+        */
+       if (__pa_symbol(_text) > __pa_symbol(VMLINUX_LOAD_ADDRESS)) {
+               unsigned long offset;
+               extern void show_kernel_relocation(const char *level);
+
+               offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS);
+               free_bootmem(__pa_symbol(VMLINUX_LOAD_ADDRESS), offset);
+
+#if defined(CONFIG_DEBUG_KERNEL) && defined(CONFIG_DEBUG_INFO)
+               /*
+                * This information is necessary when debugging the kernel
+                * But is a security vulnerability otherwise!
+                */
+               show_kernel_relocation(KERN_INFO);
+#endif
+       }
+#endif
+
        /*
         * Reserve initrd memory if needed.
         */
@@ -624,6 +672,8 @@ static void __init request_crashkernel(struct resource *res)
 #define USE_PROM_CMDLINE       IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER)
 #define USE_DTB_CMDLINE                IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB)
 #define EXTEND_WITH_PROM       IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND)
+#define BUILTIN_EXTEND_WITH_PROM       \
+       IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND)
 
 static void __init arch_mem_init(char **cmdline_p)
 {
@@ -657,15 +707,23 @@ static void __init arch_mem_init(char **cmdline_p)
                strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
 
        if (EXTEND_WITH_PROM && arcs_cmdline[0]) {
-               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               if (boot_command_line[0])
+                       strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
                strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
        }
 
 #if defined(CONFIG_CMDLINE_BOOL)
        if (builtin_cmdline[0]) {
-               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               if (boot_command_line[0])
+                       strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
                strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
        }
+
+       if (BUILTIN_EXTEND_WITH_PROM && arcs_cmdline[0]) {
+               if (boot_command_line[0])
+                       strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+       }
 #endif
 #endif
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
@@ -706,6 +764,9 @@ static void __init arch_mem_init(char **cmdline_p)
        for_each_memblock(reserved, reg)
                if (reg->size != 0)
                        reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+
+       reserve_bootmem_region(__pa_symbol(&__nosave_begin),
+                       __pa_symbol(&__nosave_end)); /* Reserve for hibernation */
 }
 
 static void __init resource_init(void)
index bf792e2839a6f31b5cde496cb84892ded60d5b5f..ab042291fbfd1a1ce396d630a842ee10d6fef00c 100644 (file)
@@ -195,6 +195,9 @@ static int restore_msa_extcontext(void __user *buf, unsigned int size)
        unsigned int csr;
        int i, err;
 
+       if (!config_enabled(CONFIG_CPU_HAS_MSA))
+               return SIGSYS;
+
        if (size != sizeof(*msa))
                return -EINVAL;
 
@@ -398,8 +401,8 @@ int protected_restore_fp_context(void __user *sc)
        }
 
 fp_done:
-       if (used & USED_EXTCONTEXT)
-               err |= restore_extcontext(sc_to_extcontext(sc));
+       if (!err && (used & USED_EXTCONTEXT))
+               err = restore_extcontext(sc_to_extcontext(sc));
 
        return err ?: sig;
 }
@@ -798,7 +801,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
                regs->regs[0] = 0;              /* Don't deal with this again.  */
        }
 
-       if (sig_uses_siginfo(&ksig->ka))
+       if (sig_uses_siginfo(&ksig->ka, abi))
                ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
                                          ksig, regs, oldset);
        else
index 4909639aa35ba7fcb3de868c4c28ca92e8f7a54e..78c8349d151c88c48b15cf6dc5d00657cf8a6c9e 100644 (file)
@@ -227,6 +227,12 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
                        err |= __put_user(from->si_uid, &to->si_uid);
                        err |= __put_user(from->si_int, &to->si_int);
                        break;
+               case __SI_SYS >> 16:
+                       err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
+                                             sizeof(compat_uptr_t));
+                       err |= __put_user(from->si_syscall, &to->si_syscall);
+                       err |= __put_user(from->si_arch, &to->si_arch);
+                       break;
                }
        }
        return err;
index 78cf8c2f1de0e8790923d25ab6e42a85e53a6fe9..e02addc0307f32454efa0db4ba22d7f7540d2bef 100644 (file)
@@ -243,6 +243,7 @@ static void bmips_init_secondary(void)
                break;
        case CPU_BMIPS5000:
                write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
+               current_cpu_data.core = (read_c0_brcm_config() >> 25) & 3;
                break;
        }
 }
@@ -565,3 +566,90 @@ asmlinkage void __weak plat_wired_tlb_setup(void)
         * once the wired entries are present.
         */
 }
+
+void __init bmips_cpu_setup(void)
+{
+       void __iomem __maybe_unused *cbr = BMIPS_GET_CBR();
+       u32 __maybe_unused cfg;
+
+       switch (current_cpu_type()) {
+       case CPU_BMIPS3300:
+               /* Set BIU to async mode */
+               set_c0_brcm_bus_pll(BIT(22));
+               __sync();
+
+               /* put the BIU back in sync mode */
+               clear_c0_brcm_bus_pll(BIT(22));
+
+               /* clear BHTD to enable branch history table */
+               clear_c0_brcm_reset(BIT(16));
+
+               /* Flush and enable RAC */
+               cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
+               __raw_writel(cfg | 0x100, BMIPS_RAC_CONFIG);
+               __raw_readl(cbr + BMIPS_RAC_CONFIG);
+
+               cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
+               __raw_writel(cfg | 0xf, BMIPS_RAC_CONFIG);
+               __raw_readl(cbr + BMIPS_RAC_CONFIG);
+
+               cfg = __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE);
+               __raw_writel(cfg | 0x0fff0000, cbr + BMIPS_RAC_ADDRESS_RANGE);
+               __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE);
+               break;
+
+       case CPU_BMIPS4380:
+               /* CBG workaround for early BMIPS4380 CPUs */
+               switch (read_c0_prid()) {
+               case 0x2a040:
+               case 0x2a042:
+               case 0x2a044:
+               case 0x2a060:
+                       cfg = __raw_readl(cbr + BMIPS_L2_CONFIG);
+                       __raw_writel(cfg & ~0x07000000, cbr + BMIPS_L2_CONFIG);
+                       __raw_readl(cbr + BMIPS_L2_CONFIG);
+               }
+
+               /* clear BHTD to enable branch history table */
+               clear_c0_brcm_config_0(BIT(21));
+
+               /* XI/ROTR enable */
+               set_c0_brcm_config_0(BIT(23));
+               set_c0_brcm_cmt_ctrl(BIT(15));
+               break;
+
+       case CPU_BMIPS5000:
+               /* enable RDHWR, BRDHWR */
+               set_c0_brcm_config(BIT(17) | BIT(21));
+
+               /* Disable JTB */
+               __asm__ __volatile__(
+               "       .set    noreorder\n"
+               "       li      $8, 0x5a455048\n"
+               "       .word   0x4088b00f\n"   /* mtc0 t0, $22, 15 */
+               "       .word   0x4008b008\n"   /* mfc0 t0, $22, 8 */
+               "       li      $9, 0x00008000\n"
+               "       or      $8, $8, $9\n"
+               "       .word   0x4088b008\n"   /* mtc0 t0, $22, 8 */
+               "       sync\n"
+               "       li      $8, 0x0\n"
+               "       .word   0x4088b00f\n"   /* mtc0 t0, $22, 15 */
+               "       .set    reorder\n"
+               : : : "$8", "$9");
+
+               /* XI enable */
+               set_c0_brcm_config(BIT(27));
+
+               /* enable MIPS32R2 ROR instruction for XI TLB handlers */
+               __asm__ __volatile__(
+               "       li      $8, 0x5a455048\n"
+               "       .word   0x4088b00f\n"   /* mtc0 $8, $22, 15 */
+               "       nop; nop; nop\n"
+               "       .word   0x4008b008\n"   /* mfc0 $8, $22, 8 */
+               "       lui     $9, 0x0100\n"
+               "       or      $8, $9\n"
+               "       .word   0x4088b008\n"   /* mtc0 $8, $22, 8 */
+               : : : "$8", "$9");
+               break;
+       }
+}
index 253e1409338c146706ffb730952fb880c30e5b5d..1061bd2e7e9cac4b5875206a1ea7eb1df9421132 100644 (file)
 #include <asm/time.h>
 #include <asm/uasm.h>
 
+static bool threads_disabled;
 static DECLARE_BITMAP(core_power, NR_CPUS);
 
 struct core_boot_config *mips_cps_core_bootcfg;
 
+static int __init setup_nothreads(char *s)
+{
+       threads_disabled = true;
+       return 0;
+}
+early_param("nothreads", setup_nothreads);
+
 static unsigned core_vpe_count(unsigned core)
 {
        unsigned cfg;
 
-       if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
+       if (threads_disabled)
+               return 1;
+
+       if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
+               && (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
                return 1;
 
        mips_cm_lock_other(core, 0);
@@ -47,11 +59,12 @@ static unsigned core_vpe_count(unsigned core)
 static void __init cps_smp_setup(void)
 {
        unsigned int ncores, nvpes, core_vpes;
+       unsigned long core_entry;
        int c, v;
 
        /* Detect & record VPE topology */
        ncores = mips_cm_numcores();
-       pr_info("VPE topology ");
+       pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE");
        for (c = nvpes = 0; c < ncores; c++) {
                core_vpes = core_vpe_count(c);
                pr_cont("%c%u", c ? ',' : '{', core_vpes);
@@ -62,7 +75,7 @@ static void __init cps_smp_setup(void)
 
                for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
                        cpu_data[nvpes + v].core = c;
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
                        cpu_data[nvpes + v].vpe_id = v;
 #endif
                }
@@ -91,6 +104,11 @@ static void __init cps_smp_setup(void)
        /* Make core 0 coherent with everything */
        write_gcr_cl_coherence(0xff);
 
+       if (mips_cm_revision() >= CM_REV_CM3) {
+               core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
+               write_gcr_bev_base(core_entry);
+       }
+
 #ifdef CONFIG_MIPS_MT_FPAFF
        /* If we have an FPU, enroll ourselves in the FPU-full mask */
        if (cpu_has_fpu)
@@ -213,6 +231,18 @@ static void boot_core(unsigned core)
        if (mips_cpc_present()) {
                /* Reset the core */
                mips_cpc_lock_other(core);
+
+               if (mips_cm_revision() >= CM_REV_CM3) {
+                       /* Run VP0 following the reset */
+                       write_cpc_co_vp_run(0x1);
+
+                       /*
+                        * Ensure that the VP_RUN register is written before the
+                        * core leaves reset.
+                        */
+                       wmb();
+               }
+
                write_cpc_co_cmd(CPC_Cx_CMD_RESET);
 
                timeout = 100;
@@ -250,7 +280,10 @@ static void boot_core(unsigned core)
 
 static void remote_vpe_boot(void *dummy)
 {
-       mips_cps_boot_vpes();
+       unsigned core = current_cpu_data.core;
+       struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
+
+       mips_cps_boot_vpes(core_cfg, cpu_vpe_id(&current_cpu_data));
 }
 
 static void cps_boot_secondary(int cpu, struct task_struct *idle)
@@ -259,6 +292,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
        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 long core_entry;
        unsigned int remote;
        int err;
 
@@ -276,6 +310,13 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
                goto out;
        }
 
+       if (cpu_has_vp) {
+               mips_cm_lock_other(core, vpe_id);
+               core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
+               write_gcr_co_reset_base(core_entry);
+               mips_cm_unlock_other();
+       }
+
        if (core != current_cpu_data.core) {
                /* Boot a VPE on another powered up core */
                for (remote = 0; remote < NR_CPUS; remote++) {
@@ -293,10 +334,10 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
                goto out;
        }
 
-       BUG_ON(!cpu_has_mipsmt);
+       BUG_ON(!cpu_has_mipsmt && !cpu_has_vp);
 
        /* Boot a VPE on this core */
-       mips_cps_boot_vpes();
+       mips_cps_boot_vpes(core_cfg, vpe_id);
 out:
        preempt_enable();
 }
@@ -307,6 +348,17 @@ static void cps_init_secondary(void)
        if (cpu_has_mipsmt)
                dmt();
 
+       if (mips_cm_revision() >= CM_REV_CM3) {
+               unsigned ident = gic_read_local_vp_id();
+
+               /*
+                * Ensure that our calculation of the VP ID matches up with
+                * what the GIC reports, otherwise we'll have configured
+                * interrupts incorrectly.
+                */
+               BUG_ON(ident != mips_cm_vp_id(smp_processor_id()));
+       }
+
        change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
                                 STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7);
 }
index 27cb638f082414048b6655eb04fc36b3b064eec1..f9d01e953acb8b8c2042d932b4a2159d09769350 100644 (file)
@@ -243,18 +243,6 @@ static int __init mips_smp_ipi_init(void)
        struct irq_domain *ipidomain;
        struct device_node *node;
 
-       /*
-        * In some cases like qemu-malta, it is desired to try SMP with
-        * a single core. Qemu-malta has no GIC, so an attempt to set any IPIs
-        * would cause a BUG_ON() to be triggered since there's no ipidomain.
-        *
-        * Since for a single core system IPIs aren't required really, skip the
-        * initialisation which should generally keep any such configurations
-        * happy and only fail hard when trying to truely run SMP.
-        */
-       if (cpumask_weight(cpu_possible_mask) == 1)
-               return 0;
-
        node = of_irq_find_parent(of_root);
        ipidomain = irq_find_matching_host(node, DOMAIN_BUS_IPI);
 
@@ -266,7 +254,17 @@ static int __init mips_smp_ipi_init(void)
        if (node && !ipidomain)
                ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI);
 
-       BUG_ON(!ipidomain);
+       /*
+        * There are systems which only use IPI domains some of the time,
+        * depending upon configuration we don't know until runtime. An
+        * example is Malta where we may compile in support for GIC & the
+        * MT ASE, but run on a system which has multiple VPEs in a single
+        * core and doesn't include a GIC. Until all IPI implementations
+        * have been converted to use IPI domains the best we can do here
+        * is to return & hope some other code sets up the IPIs.
+        */
+       if (!ipidomain)
+               return 0;
 
        call_virq = irq_reserve_ipi(ipidomain, cpu_possible_mask);
        BUG_ON(!call_virq);
index 8489c88f9932310b7732e1ec396ca2fb2000078c..d6e6cf75114d633f89b0b81a352a6fac052e99de 100644 (file)
@@ -210,6 +210,7 @@ void spram_config(void)
        case CPU_P5600:
        case CPU_QEMU_GENERIC:
        case CPU_I6400:
+       case CPU_P6600:
                config0 = read_c0_config();
                /* FIXME: addresses are Malta specific */
                if (config0 & (1<<24)) {
index ae0c89d23ad7d3e41a068f4178b69fec492e2252..4a1712b5abdff6a2d3f3548901a479a05cb250ea 100644 (file)
@@ -145,7 +145,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
        if (!task)
                task = current;
 
-       if (raw_show_trace || !__kernel_text_address(pc)) {
+       if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) {
                show_raw_backtrace(sp);
                return;
        }
@@ -399,11 +399,8 @@ void __noreturn die(const char *str, struct pt_regs *regs)
        if (in_interrupt())
                panic("Fatal exception in interrupt");
 
-       if (panic_on_oops) {
-               printk(KERN_EMERG "Fatal exception: panic in 5 seconds");
-               ssleep(5);
+       if (panic_on_oops)
                panic("Fatal exception");
-       }
 
        if (regs && kexec_should_crash(current))
                crash_kexec(regs);
@@ -1249,7 +1246,7 @@ static int enable_restore_fp_context(int msa)
                err = init_fpu();
                if (msa && !err) {
                        enable_msa();
-                       _init_msa_upper();
+                       init_msa_upper();
                        set_thread_flag(TIF_USEDMSA);
                        set_thread_flag(TIF_MSA_CTX_LIVE);
                }
@@ -1312,7 +1309,7 @@ static int enable_restore_fp_context(int msa)
         */
        prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
        if (!prior_msa && was_fpu_owner) {
-               _init_msa_upper();
+               init_msa_upper();
 
                goto out;
        }
@@ -1329,7 +1326,7 @@ static int enable_restore_fp_context(int msa)
                 * of each vector register such that it cannot see data left
                 * behind by another task.
                 */
-               _init_msa_upper();
+               init_msa_upper();
        } else {
                /* We need to restore the vector context. */
                restore_msa(current);
@@ -1356,7 +1353,6 @@ asmlinkage void do_cpu(struct pt_regs *regs)
        unsigned long fcr31;
        unsigned int cpid;
        int status, err;
-       unsigned long __maybe_unused flags;
        int sig;
 
        prev_state = exception_enter();
@@ -1501,16 +1497,13 @@ asmlinkage void do_watch(struct pt_regs *regs)
 {
        siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
        enum ctx_state prev_state;
-       u32 cause;
 
        prev_state = exception_enter();
        /*
         * Clear WP (bit 22) bit of cause register so we don't loop
         * forever.
         */
-       cause = read_c0_cause();
-       cause &= ~(1 << 22);
-       write_c0_cause(cause);
+       clear_c0_cause(CAUSEF_WP);
 
        /*
         * If the current thread has the watch registers loaded, save
@@ -1647,6 +1640,7 @@ static inline void parity_protection_init(void)
        case CPU_P5600:
        case CPU_QEMU_GENERIC:
        case CPU_I6400:
+       case CPU_P6600:
                {
 #define ERRCTL_PE      0x80000000
 #define ERRCTL_L2P     0x00800000
@@ -1777,7 +1771,8 @@ asmlinkage void do_ftlb(void)
 
        /* For the moment, report the problem and hang. */
        if ((cpu_has_mips_r2_r6) &&
-           ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
+           (((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS) ||
+           ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_LOONGSON))) {
                pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
                       read_c0_ecc());
                pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
@@ -2119,6 +2114,13 @@ void per_cpu_trap_init(bool is_boot_cpu)
         *  o read IntCtl.IPFDC to determine the fast debug channel interrupt
         */
        if (cpu_has_mips_r2_r6) {
+               /*
+                * We shouldn't trust a secondary core has a sane EBASE register
+                * so use the one calculated by the boot CPU.
+                */
+               if (!is_boot_cpu)
+                       write_c0_ebase(ebase);
+
                cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
                cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
                cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
@@ -2134,7 +2136,7 @@ void per_cpu_trap_init(bool is_boot_cpu)
        }
 
        if (!cpu_data[cpu].asid_cache)
-               cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+               cpu_data[cpu].asid_cache = asid_first_version(cpu);
 
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
index 5c62065cbf22d610323331b8d3bd56e6e53fa793..28b3af73a17b2bb00018bb6feee1e93eae2332fc 100644 (file)
@@ -1191,6 +1191,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
        case ldc1_op:
        case swc1_op:
        case sdc1_op:
+       case cop1x_op:
                die_if_kernel("Unaligned FP access in kernel code", regs);
                BUG_ON(!used_math());
 
index 54d653ee17e1a8f3e2887bf76b1849fcaf73c27d..a82c178d0bb97c8e47b778945af384af620431ea 100644 (file)
@@ -136,6 +136,27 @@ SECTIONS
 #ifdef CONFIG_SMP
        PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
 #endif
+
+#ifdef CONFIG_RELOCATABLE
+       . = ALIGN(4);
+
+       .data.reloc : {
+               _relocation_start = .;
+               /*
+                * Space for relocation table
+                * This needs to be filled so that the
+                * relocs tool can overwrite the content.
+                * An invalid value is left at the start of the
+                * section to abort relocation if the table
+                * has not been filled in.
+                */
+               LONG(0xFFFFFFFF);
+               FILL(0);
+               . += CONFIG_RELOCATION_TABLE_SIZE - 4;
+               _relocation_end = .;
+       }
+#endif
+
 #ifdef CONFIG_MIPS_RAW_APPENDED_DTB
        __appended_dtb = .;
        /* leave space for appended DTB */
index 2a03abb5bd2cc24e9aa7d4dd6c6fcfa29cb253ed..19fcab7348b16d9ab8538fdc8b83c342ac7a8486 100644 (file)
  * Install the watch registers for the current thread. A maximum of
  * four registers are installed although the machine may have more.
  */
-void mips_install_watch_registers(void)
+void mips_install_watch_registers(struct task_struct *t)
 {
-       struct mips3264_watch_reg_state *watches =
-               &current->thread.watch.mips3264;
+       struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264;
        switch (current_cpu_data.watch_reg_use_cnt) {
        default:
                BUG();
@@ -26,16 +25,20 @@ void mips_install_watch_registers(void)
                write_c0_watchlo3(watches->watchlo[3]);
                /* Write 1 to the I, R, and W bits to clear them, and
                   1 to G so all ASIDs are trapped. */
-               write_c0_watchhi3(0x40000007 | watches->watchhi[3]);
+               write_c0_watchhi3(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+                                 watches->watchhi[3]);
        case 3:
                write_c0_watchlo2(watches->watchlo[2]);
-               write_c0_watchhi2(0x40000007 | watches->watchhi[2]);
+               write_c0_watchhi2(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+                                 watches->watchhi[2]);
        case 2:
                write_c0_watchlo1(watches->watchlo[1]);
-               write_c0_watchhi1(0x40000007 | watches->watchhi[1]);
+               write_c0_watchhi1(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+                                 watches->watchhi[1]);
        case 1:
                write_c0_watchlo0(watches->watchlo[0]);
-               write_c0_watchhi0(0x40000007 | watches->watchhi[0]);
+               write_c0_watchhi0(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+                                 watches->watchhi[0]);
        }
 }
 
@@ -52,22 +55,26 @@ void mips_read_watch_registers(void)
        default:
                BUG();
        case 4:
-               watches->watchhi[3] = (read_c0_watchhi3() & 0x0fff);
+               watches->watchhi[3] = (read_c0_watchhi3() &
+                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
        case 3:
-               watches->watchhi[2] = (read_c0_watchhi2() & 0x0fff);
+               watches->watchhi[2] = (read_c0_watchhi2() &
+                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
        case 2:
-               watches->watchhi[1] = (read_c0_watchhi1() & 0x0fff);
+               watches->watchhi[1] = (read_c0_watchhi1() &
+                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
        case 1:
-               watches->watchhi[0] = (read_c0_watchhi0() & 0x0fff);
+               watches->watchhi[0] = (read_c0_watchhi0() &
+                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
        }
        if (current_cpu_data.watch_reg_use_cnt == 1 &&
-           (watches->watchhi[0] & 7) == 0) {
+           (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) {
                /* Pathological case of release 1 architecture that
                 * doesn't set the condition bits.  We assume that
                 * since we got here, the watch condition was met and
                 * signal that the conditions requested in watchlo
                 * were met.  */
-               watches->watchhi[0] |= (watches->watchlo[0] & 7);
+               watches->watchhi[0] |= (watches->watchlo[0] & MIPS_WATCHHI_IRW);
        }
  }
 
@@ -110,86 +117,86 @@ void mips_probe_watch_registers(struct cpuinfo_mips *c)
         * Check which of the I,R and W bits are supported, then
         * disable the register.
         */
-       write_c0_watchlo0(7);
+       write_c0_watchlo0(MIPS_WATCHLO_IRW);
        back_to_back_c0_hazard();
        t = read_c0_watchlo0();
        write_c0_watchlo0(0);
-       c->watch_reg_masks[0] = t & 7;
+       c->watch_reg_masks[0] = t & MIPS_WATCHLO_IRW;
 
        /* Write the mask bits and read them back to determine which
         * can be used. */
        c->watch_reg_count = 1;
        c->watch_reg_use_cnt = 1;
        t = read_c0_watchhi0();
-       write_c0_watchhi0(t | 0xff8);
+       write_c0_watchhi0(t | MIPS_WATCHHI_MASK);
        back_to_back_c0_hazard();
        t = read_c0_watchhi0();
-       c->watch_reg_masks[0] |= (t & 0xff8);
-       if ((t & 0x80000000) == 0)
+       c->watch_reg_masks[0] |= (t & MIPS_WATCHHI_MASK);
+       if ((t & MIPS_WATCHHI_M) == 0)
                return;
 
-       write_c0_watchlo1(7);
+       write_c0_watchlo1(MIPS_WATCHLO_IRW);
        back_to_back_c0_hazard();
        t = read_c0_watchlo1();
        write_c0_watchlo1(0);
-       c->watch_reg_masks[1] = t & 7;
+       c->watch_reg_masks[1] = t & MIPS_WATCHLO_IRW;
 
        c->watch_reg_count = 2;
        c->watch_reg_use_cnt = 2;
        t = read_c0_watchhi1();
-       write_c0_watchhi1(t | 0xff8);
+       write_c0_watchhi1(t | MIPS_WATCHHI_MASK);
        back_to_back_c0_hazard();
        t = read_c0_watchhi1();
-       c->watch_reg_masks[1] |= (t & 0xff8);
-       if ((t & 0x80000000) == 0)
+       c->watch_reg_masks[1] |= (t & MIPS_WATCHHI_MASK);
+       if ((t & MIPS_WATCHHI_M) == 0)
                return;
 
-       write_c0_watchlo2(7);
+       write_c0_watchlo2(MIPS_WATCHLO_IRW);
        back_to_back_c0_hazard();
        t = read_c0_watchlo2();
        write_c0_watchlo2(0);
-       c->watch_reg_masks[2] = t & 7;
+       c->watch_reg_masks[2] = t & MIPS_WATCHLO_IRW;
 
        c->watch_reg_count = 3;
        c->watch_reg_use_cnt = 3;
        t = read_c0_watchhi2();
-       write_c0_watchhi2(t | 0xff8);
+       write_c0_watchhi2(t | MIPS_WATCHHI_MASK);
        back_to_back_c0_hazard();
        t = read_c0_watchhi2();
-       c->watch_reg_masks[2] |= (t & 0xff8);
-       if ((t & 0x80000000) == 0)
+       c->watch_reg_masks[2] |= (t & MIPS_WATCHHI_MASK);
+       if ((t & MIPS_WATCHHI_M) == 0)
                return;
 
-       write_c0_watchlo3(7);
+       write_c0_watchlo3(MIPS_WATCHLO_IRW);
        back_to_back_c0_hazard();
        t = read_c0_watchlo3();
        write_c0_watchlo3(0);
-       c->watch_reg_masks[3] = t & 7;
+       c->watch_reg_masks[3] = t & MIPS_WATCHLO_IRW;
 
        c->watch_reg_count = 4;
        c->watch_reg_use_cnt = 4;
        t = read_c0_watchhi3();
-       write_c0_watchhi3(t | 0xff8);
+       write_c0_watchhi3(t | MIPS_WATCHHI_MASK);
        back_to_back_c0_hazard();
        t = read_c0_watchhi3();
-       c->watch_reg_masks[3] |= (t & 0xff8);
-       if ((t & 0x80000000) == 0)
+       c->watch_reg_masks[3] |= (t & MIPS_WATCHHI_MASK);
+       if ((t & MIPS_WATCHHI_M) == 0)
                return;
 
        /* We use at most 4, but probe and report up to 8. */
        c->watch_reg_count = 5;
        t = read_c0_watchhi4();
-       if ((t & 0x80000000) == 0)
+       if ((t & MIPS_WATCHHI_M) == 0)
                return;
 
        c->watch_reg_count = 6;
        t = read_c0_watchhi5();
-       if ((t & 0x80000000) == 0)
+       if ((t & MIPS_WATCHHI_M) == 0)
                return;
 
        c->watch_reg_count = 7;
        t = read_c0_watchhi6();
-       if ((t & 0x80000000) == 0)
+       if ((t & MIPS_WATCHHI_M) == 0)
                return;
 
        c->watch_reg_count = 8;
index b37954cc880d6ce06d9ca408962a4fabf7e7de06..8e945e866a7379ecc2cf770d8c3b0f2646b6e06c 100644 (file)
@@ -1068,15 +1068,15 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
                                        kvm_read_c0_guest_ebase(cop0));
                        } else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
                                uint32_t nasid =
-                                       vcpu->arch.gprs[rt] & ASID_MASK;
+                                       vcpu->arch.gprs[rt] & KVM_ENTRYHI_ASID;
                                if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) &&
                                    ((kvm_read_c0_guest_entryhi(cop0) &
-                                     ASID_MASK) != nasid)) {
+                                     KVM_ENTRYHI_ASID) != nasid)) {
                                        kvm_debug("MTCz, change ASID from %#lx to %#lx\n",
                                                kvm_read_c0_guest_entryhi(cop0)
-                                               & ASID_MASK,
+                                               & KVM_ENTRYHI_ASID,
                                                vcpu->arch.gprs[rt]
-                                               & ASID_MASK);
+                                               & KVM_ENTRYHI_ASID);
 
                                        /* Blow away the shadow host TLBs */
                                        kvm_mips_flush_host_tlb(1);
@@ -1620,7 +1620,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
                 */
                index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
                                                  (kvm_read_c0_guest_entryhi
-                                                  (cop0) & ASID_MASK));
+                                                  (cop0) & KVM_ENTRYHI_ASID));
 
                if (index < 0) {
                        vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
@@ -1786,7 +1786,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause,
        struct mips_coproc *cop0 = vcpu->arch.cop0;
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        unsigned long entryhi = (vcpu->arch.  host_cp0_badvaddr & VPN2_MASK) |
-                               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+                       (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1833,7 +1833,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause,
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        unsigned long entryhi =
                (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+               (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1878,7 +1878,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause,
        struct mips_coproc *cop0 = vcpu->arch.cop0;
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-                               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+                       (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1922,7 +1922,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause,
        struct mips_coproc *cop0 = vcpu->arch.cop0;
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+               (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1967,7 +1967,7 @@ enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
 #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);
+                       (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
        int index;
 
        /* If address not in the guest TLB, then we are in trouble */
@@ -1994,7 +1994,7 @@ enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause,
 {
        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);
+                       (kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
        struct kvm_vcpu_arch *arch = &vcpu->arch;
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
@@ -2569,7 +2569,8 @@ enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
         */
        index = kvm_mips_guest_tlb_lookup(vcpu,
                      (va & VPN2_MASK) |
-                     (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & ASID_MASK));
+                     (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) &
+                      KVM_ENTRYHI_ASID));
        if (index < 0) {
                if (exccode == EXCCODE_TLBL) {
                        er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
index 81687ab1b523eaebce4f2edbaeffc3b515a1b9e9..3ef03009de5f65fa4807cac71bb9749baaa63ab7 100644 (file)
@@ -32,7 +32,6 @@
     EXPORT(x);
 
 /* Overload, Danger Will Robinson!! */
-#define PT_HOST_ASID        PT_BVADDR
 #define PT_HOST_USERLOCAL   PT_EPC
 
 #define CP0_DDATA_LO        $28,3
  * a1: vcpu
  */
        .set    noreorder
-       .set    noat
 
 FEXPORT(__kvm_mips_vcpu_run)
        /* k0/k1 not being used in host kernel context */
        INT_ADDIU k1, sp, -PT_SIZE
-       LONG_S  $0, PT_R0(k1)
-       LONG_S  $1, PT_R1(k1)
-       LONG_S  $2, PT_R2(k1)
-       LONG_S  $3, PT_R3(k1)
-
-       LONG_S  $4, PT_R4(k1)
-       LONG_S  $5, PT_R5(k1)
-       LONG_S  $6, PT_R6(k1)
-       LONG_S  $7, PT_R7(k1)
-
-       LONG_S  $8,  PT_R8(k1)
-       LONG_S  $9,  PT_R9(k1)
-       LONG_S  $10, PT_R10(k1)
-       LONG_S  $11, PT_R11(k1)
-       LONG_S  $12, PT_R12(k1)
-       LONG_S  $13, PT_R13(k1)
-       LONG_S  $14, PT_R14(k1)
-       LONG_S  $15, PT_R15(k1)
        LONG_S  $16, PT_R16(k1)
        LONG_S  $17, PT_R17(k1)
-
        LONG_S  $18, PT_R18(k1)
        LONG_S  $19, PT_R19(k1)
        LONG_S  $20, PT_R20(k1)
        LONG_S  $21, PT_R21(k1)
        LONG_S  $22, PT_R22(k1)
        LONG_S  $23, PT_R23(k1)
-       LONG_S  $24, PT_R24(k1)
-       LONG_S  $25, PT_R25(k1)
-
-       /*
-        * XXXKYMA k0/k1 not saved, not being used if we got here through
-        * an ioctl()
-        */
 
        LONG_S  $28, PT_R28(k1)
        LONG_S  $29, PT_R29(k1)
@@ -104,11 +76,6 @@ FEXPORT(__kvm_mips_vcpu_run)
        mfc0    v0, CP0_STATUS
        LONG_S  v0, PT_STATUS(k1)
 
-       /* Save host ASID, shove it into the BVADDR location */
-       mfc0    v1, CP0_ENTRYHI
-       andi    v1, 0xff
-       LONG_S  v1, PT_HOST_ASID(k1)
-
        /* Save DDATA_LO, will be used to store pointer to vcpu */
        mfc0    v1, CP0_DDATA_LO
        LONG_S  v1, PT_HOST_USERLOCAL(k1)
@@ -170,13 +137,21 @@ FEXPORT(__kvm_mips_load_asid)
        INT_SLL t2, t2, 2                   /* x4 */
        REG_ADDU t3, t1, t2
        LONG_L  k0, (t3)
-       andi    k0, k0, 0xff
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       li      t3, CPUINFO_SIZE/4
+       mul     t2, t2, t3              /* x sizeof(struct cpuinfo_mips)/4 */
+       LONG_L  t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
+       and     k0, k0, t2
+#else
+       andi    k0, k0, MIPS_ENTRYHI_ASID
+#endif
        mtc0    k0, CP0_ENTRYHI
        ehb
 
        /* Disable RDHWR access */
        mtc0    zero, CP0_HWRENA
 
+       .set    noat
        /* Now load up the Guest Context from VCPU */
        LONG_L  $1, VCPU_R1(k1)
        LONG_L  $2, VCPU_R2(k1)
@@ -288,6 +263,8 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
        LONG_S  $30, VCPU_R30(k1)
        LONG_S  $31, VCPU_R31(k1)
 
+       .set at
+
        /* We need to save hi/lo and restore them on the way out */
        mfhi    t0
        LONG_S  t0, VCPU_HI(k1)
@@ -339,9 +316,7 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
        /* load up the host EBASE */
        mfc0    v0, CP0_STATUS
 
-       .set    at
        or      k0, v0, ST0_BEV
-       .set    noat
 
        mtc0    k0, CP0_STATUS
        ehb
@@ -353,7 +328,6 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
         * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
         * trigger FPE for pending exceptions.
         */
-       .set    at
        and     v1, v0, ST0_CU1
        beqz    v1, 1f
         nop
@@ -363,7 +337,6 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
        sw      t0, VCPU_FCR31(k1)
        ctc1    zero,fcr31
        .set    pop
-       .set    noat
 1:
 
 #ifdef CONFIG_CPU_HAS_MSA
@@ -386,10 +359,8 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
 #endif
 
        /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
-       .set    at
        and     v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
        or      v0, v0, ST0_CU0
-       .set    noat
        mtc0    v0, CP0_STATUS
        ehb
 
@@ -456,18 +427,14 @@ __kvm_mips_return_to_guest:
 
        /* Switch EBASE back to the one used by KVM */
        mfc0    v1, CP0_STATUS
-       .set    at
        or      k0, v1, ST0_BEV
-       .set    noat
        mtc0    k0, CP0_STATUS
        ehb
        mtc0    t0, CP0_EBASE
 
        /* Setup status register for running guest in UM */
-       .set    at
        or      v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
        and     v1, v1, ~(ST0_CU0 | ST0_MX)
-       .set    noat
        mtc0    v1, CP0_STATUS
        ehb
 
@@ -489,13 +456,21 @@ __kvm_mips_return_to_guest:
        INT_SLL t2, t2, 2               /* x4 */
        REG_ADDU t3, t1, t2
        LONG_L  k0, (t3)
-       andi    k0, k0, 0xff
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       li      t3, CPUINFO_SIZE/4
+       mul     t2, t2, t3              /* x sizeof(struct cpuinfo_mips)/4 */
+       LONG_L  t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
+       and     k0, k0, t2
+#else
+       andi    k0, k0, MIPS_ENTRYHI_ASID
+#endif
        mtc0    k0, CP0_ENTRYHI
        ehb
 
        /* Disable RDHWR access */
        mtc0    zero, CP0_HWRENA
 
+       .set    noat
        /* load the guest context from VCPU and return */
        LONG_L  $0, VCPU_R0(k1)
        LONG_L  $1, VCPU_R1(k1)
@@ -541,6 +516,7 @@ FEXPORT(__kvm_mips_skip_guest_restore)
        LONG_L  k1, VCPU_R27(k1)
 
        eret
+       .set    at
 
 __kvm_mips_return_to_host:
        /* EBASE is already pointing to Linux */
@@ -551,16 +527,6 @@ __kvm_mips_return_to_host:
        LONG_L  k0, PT_HOST_USERLOCAL(k1)
        mtc0    k0, CP0_DDATA_LO
 
-       /* Restore host ASID */
-       LONG_L  k0, PT_HOST_ASID(sp)
-       andi    k0, 0xff
-       mtc0    k0,CP0_ENTRYHI
-       ehb
-
-       /* Load context saved on the host stack */
-       LONG_L  $0, PT_R0(k1)
-       LONG_L  $1, PT_R1(k1)
-
        /*
         * r2/v0 is the return code, shift it down by 2 (arithmetic)
         * to recover the err code
@@ -568,19 +534,7 @@ __kvm_mips_return_to_host:
        INT_SRA k0, v0, 2
        move    $2, k0
 
-       LONG_L  $3, PT_R3(k1)
-       LONG_L  $4, PT_R4(k1)
-       LONG_L  $5, PT_R5(k1)
-       LONG_L  $6, PT_R6(k1)
-       LONG_L  $7, PT_R7(k1)
-       LONG_L  $8, PT_R8(k1)
-       LONG_L  $9, PT_R9(k1)
-       LONG_L  $10, PT_R10(k1)
-       LONG_L  $11, PT_R11(k1)
-       LONG_L  $12, PT_R12(k1)
-       LONG_L  $13, PT_R13(k1)
-       LONG_L  $14, PT_R14(k1)
-       LONG_L  $15, PT_R15(k1)
+       /* Load context saved on the host stack */
        LONG_L  $16, PT_R16(k1)
        LONG_L  $17, PT_R17(k1)
        LONG_L  $18, PT_R18(k1)
@@ -589,10 +543,6 @@ __kvm_mips_return_to_host:
        LONG_L  $21, PT_R21(k1)
        LONG_L  $22, PT_R22(k1)
        LONG_L  $23, PT_R23(k1)
-       LONG_L  $24, PT_R24(k1)
-       LONG_L  $25, PT_R25(k1)
-
-       /* Host k0/k1 were not saved */
 
        LONG_L  $28, PT_R28(k1)
        LONG_L  $29, PT_R29(k1)
index e0e1d0a611fc2bd102d10ad2ecec3ae3f6951551..b9c52c1d35d6a37f181d843819d835b341f5958b 100644 (file)
@@ -49,12 +49,18 @@ EXPORT_SYMBOL_GPL(kvm_mips_is_error_pfn);
 
 uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
 {
-       return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
+       int cpu = smp_processor_id();
+
+       return vcpu->arch.guest_kernel_asid[cpu] &
+                       cpu_asid_mask(&cpu_data[cpu]);
 }
 
 uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
 {
-       return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
+       int cpu = smp_processor_id();
+
+       return vcpu->arch.guest_user_asid[cpu] &
+                       cpu_asid_mask(&cpu_data[cpu]);
 }
 
 inline uint32_t kvm_mips_get_commpage_asid(struct kvm_vcpu *vcpu)
@@ -78,7 +84,8 @@ void kvm_mips_dump_host_tlbs(void)
        old_pagemask = read_c0_pagemask();
 
        kvm_info("HOST TLBs:\n");
-       kvm_info("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
+       kvm_info("ASID: %#lx\n", read_c0_entryhi() &
+                cpu_asid_mask(&current_cpu_data));
 
        for (i = 0; i < current_cpu_data.tlbsize; i++) {
                write_c0_index(i);
@@ -564,15 +571,15 @@ void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
 {
        unsigned long asid = asid_cache(cpu);
 
-       asid += ASID_INC;
-       if (!(asid & ASID_MASK)) {
+       asid += cpu_asid_inc();
+       if (!(asid & cpu_asid_mask(&cpu_data[cpu]))) {
                if (cpu_has_vtag_icache)
                        flush_icache_all();
 
                kvm_local_flush_tlb_all();      /* start new asid cycle */
 
                if (!asid)      /* fix version if needed */
-                       asid = ASID_FIRST_VERSION;
+                       asid = asid_first_version(cpu);
        }
 
        cpu_context(cpu, mm) = asid_cache(cpu) = asid;
@@ -627,6 +634,7 @@ static void kvm_mips_migrate_count(struct kvm_vcpu *vcpu)
 /* Restore ASID once we are scheduled back after preemption */
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+       unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]);
        unsigned long flags;
        int newasid = 0;
 
@@ -637,7 +645,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        local_irq_save(flags);
 
        if ((vcpu->arch.guest_kernel_asid[cpu] ^ asid_cache(cpu)) &
-                                                       ASID_VERSION_MASK) {
+                                               asid_version_mask(cpu)) {
                kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu);
                vcpu->arch.guest_kernel_asid[cpu] =
                    vcpu->arch.guest_kernel_mm.context.asid[cpu];
@@ -672,7 +680,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                 */
                if (current->flags & PF_VCPU) {
                        write_c0_entryhi(vcpu->arch.
-                                        preempt_entryhi & ASID_MASK);
+                                        preempt_entryhi & asid_mask);
                        ehb();
                }
        } else {
@@ -687,11 +695,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                        if (KVM_GUEST_KERNEL_MODE(vcpu))
                                write_c0_entryhi(vcpu->arch.
                                                 guest_kernel_asid[cpu] &
-                                                ASID_MASK);
+                                                asid_mask);
                        else
                                write_c0_entryhi(vcpu->arch.
                                                 guest_user_asid[cpu] &
-                                                ASID_MASK);
+                                                asid_mask);
                        ehb();
                }
        }
@@ -721,7 +729,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
        kvm_mips_callbacks->vcpu_get_regs(vcpu);
 
        if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) &
-            ASID_VERSION_MASK)) {
+            asid_version_mask(cpu))) {
                kvm_debug("%s: Dropping MMU Context:  %#lx\n", __func__,
                          cpu_context(cpu, current->mm));
                drop_mmu_context(current->mm, cpu);
@@ -748,7 +756,8 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
                        inst = *(opc);
                } else {
                        vpn2 = (unsigned long) opc & VPN2_MASK;
-                       asid = kvm_read_c0_guest_entryhi(cop0) & ASID_MASK;
+                       asid = kvm_read_c0_guest_entryhi(cop0) &
+                                               KVM_ENTRYHI_ASID;
                        index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid);
                        if (index < 0) {
                                kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
index c4038d2a724c0df9746a75c67c358deb3d620071..fd43f0afdb9f0b2f31a78a4f8b6b89d34a906315 100644 (file)
@@ -505,7 +505,8 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
        kvm_write_c0_guest_intctl(cop0, 0xFC000000);
 
        /* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */
-       kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF));
+       kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 |
+                                      (vcpu_id & MIPS_EBASE_CPUNUM));
 
        return 0;
 }
index e10d33342b30209c816d7ee929ce11a894531f89..177769dbb0e85df724bd5da31951a46bfe544842 100644 (file)
@@ -25,7 +25,17 @@ config SOC_FALCON
 endchoice
 
 choice
-       prompt "Devicetree"
+       prompt "Built-in device tree"
+       help
+         Legacy bootloaders do not pass a DTB pointer to the kernel, so
+         if a "wrapper" is not being used, the kernel will need to include
+         a device tree that matches the target board.
+
+         The builtin DTB will only be used if the firmware does not supply
+         a valid DTB.
+
+config LANTIQ_DT_NONE
+       bool "None"
 
 config DT_EASY50712
        bool "Easy50712"
index 690257ab86d60bf2fc8f7ead3268d483e8fbfb3f..2718652e74666c60ccb66520082cc8aa458939ca 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+# Copyright (C) 2010 John Crispin <john@phrozen.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
index a0706fd4ce0a0f0b3e9a531b31692fd6e1c0342f..149f0513c4f5d0d4d5f37dfc009b1684eae5df07 100644 (file)
@@ -4,7 +4,7 @@
  *  by the Free Software Foundation.
  *
  * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 #include <linux/io.h>
 #include <linux/export.h>
index 7376ce817eda6c6d23a20f1d1c853c24ccd5eb27..e806e048ffc2868c2b695d3a3db930ffdb77792a 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_CLK_H__
index 9b28d0940ef4c9c444ae811f3ba55d6aa01ea45b..44bccaee822b1f6ebcb827f039cc73eab2b7f634 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/cpu.h>
index aa9497947859ed99dc993e12443f162906709094..75315c0a9fc31d1d5694e3cf1f7896733e7ec987 100644 (file)
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
index 56824825342644db60b4cb0cc30a3e1118747fe1..7a535d72f541afbe03f4c413afc92756f505e634 100644 (file)
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
index 7edcd4946fc11ffccec557427a8eb5963fdbd43a..2a1b3021589cf111aa26f57f0e8250534fd13f9a 100644 (file)
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2011 John Crispin <john@phrozen.org>
  */
 
 #include <linux/ioport.h>
index 2e7f60c9fc5dfc9a56f3d5db2aed46fcbffc6002..ff17669e30a36363530358cf9f2301fbc0eb129d 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
  */
 
index 297bcaa6b5d32b346c25fc9414a1e4690094c092..5f693ac77a0df2a979f0ec2d75717d81397bbead 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/export.h>
@@ -65,6 +65,8 @@ static void __init prom_init_cmdline(void)
 
 void __init plat_mem_setup(void)
 {
+       void *dtb;
+
        ioport_resource.start = IOPORT_RESOURCE_START;
        ioport_resource.end = IOPORT_RESOURCE_END;
        iomem_resource.start = IOMEM_RESOURCE_START;
@@ -72,11 +74,18 @@ void __init plat_mem_setup(void)
 
        set_io_port_base((unsigned long) KSEG1);
 
+       if (fw_arg0 == -2) /* UHI interface */
+               dtb = (void *)fw_arg1;
+       else if (__dtb_start != __dtb_end)
+               dtb = (void *)__dtb_start;
+       else
+               panic("no dtb found");
+
        /*
-        * Load the builtin devicetree. This causes the chosen node to be
+        * Load the devicetree. This causes the chosen node to be
         * parsed resulting in our memory appearing
         */
-       __dt_setup_arch(__dtb_start);
+       __dt_setup_arch(dtb);
 }
 
 void __init device_tree_init(void)
index bfd2d58c1d69fa0e3c3cd55298af9493a5f04c87..4b6576c50250ad09e73478f49fdf9c4bc0d61243 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_PROM_H__
index 07f6d5b0b65ee10ccca231e0abab24d08462332e..41fc30d8ef897d30db03f760a026031fab109157 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
index ae8e930f5283c465a99e0d9441e48951153320c8..08f7abaadfe598276b74c7bd9c8a0654a76128e2 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  *  Copyright (C) 2010 Sameer Ahmad, Lantiq GmbH
  */
 
index 34a116e840d8ba4a4d1843be6d98b14ea1232143..cef811755123f4749f93b78880f5dffa4bcdc5e1 100644 (file)
@@ -12,7 +12,7 @@
  *   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) 2011 John Crispin <blogic@openwrt.org>
+ *   Copyright (C) 2011 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
index f1492b2db017b18ef106ad7fccddfb76741a31c5..0f1bbea1a816695e1df3e454b26833258b2fea81 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  *  Copyright (C) 2012 Lantiq GmbH
  */
 
index 8f6e02f1e9650b99830a14bd160ddf12856a9ee1..9475b2510adbfb680361f74a1a3159446352fc69 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
index bc29bb349e94e227fc0b015544d588eddafe5a57..83fd65d76e81d836b982534054f2afe1e7676172 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
@@ -258,7 +258,7 @@ static int ltq_reset_device(struct reset_controller_dev *rcdev,
        return ltq_deassert_device(rcdev, id);
 }
 
-static struct reset_control_ops reset_ops = {
+static const struct reset_control_ops reset_ops = {
        .reset = ltq_reset_device,
        .assert = ltq_assert_device,
        .deassert = ltq_deassert_device,
index 80554e8f603758f78352b8eb3a8fa4d20df9af7f..236193b5210b0f48e78faaa42bf9fd83bc6e050e 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2011-2012 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
index d001bc38908a19f24c853dd0cffafff26885f61c..4625495f9230aa97dbdf2d51b8eb9157d1debcbc 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/module.h>
index 199094a40c1558938000b602da9e92cdeca5ac80..71e518c1e7e7500782420ee2c68279d178dc9694 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/delay.h>
@@ -112,6 +112,6 @@ static struct platform_driver xway_phy_driver = {
 
 module_platform_driver(xway_phy_driver);
 
-MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_AUTHOR("John Crispin <john@phrozen.org>");
 MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
 MODULE_LICENSE("GPL");
index 92a37319efbe9a7498c6b38cd119abdd4c35b218..0f80b936e75ec92015d1ebdfb815dfaed14a9909 100644 (file)
@@ -19,6 +19,8 @@ void dump_tlb_regs(void)
 
        pr_info("Index    : %0x\n", read_c0_index());
        pr_info("PageMask : %0x\n", read_c0_pagemask());
+       if (cpu_has_guestid)
+               pr_info("GuestCtl1: %0x\n", read_c0_guestctl1());
        pr_info("EntryHi  : %0*lx\n", field, read_c0_entryhi());
        pr_info("EntryLo0 : %0*lx\n", field, read_c0_entrylo0());
        pr_info("EntryLo1 : %0*lx\n", field, read_c0_entrylo1());
@@ -72,7 +74,10 @@ static void dump_tlb(int first, int last)
 {
        unsigned long s_entryhi, entryhi, asid;
        unsigned long long entrylo0, entrylo1, pa;
-       unsigned int s_index, s_pagemask, pagemask, c0, c1, i;
+       unsigned int s_index, s_pagemask, s_guestctl1 = 0;
+       unsigned int pagemask, guestctl1 = 0, c0, c1, i;
+       unsigned long asidmask = cpu_asid_mask(&current_cpu_data);
+       int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4);
 #ifdef CONFIG_32BIT
        bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA);
        int pwidth = xpa ? 11 : 8;
@@ -86,7 +91,9 @@ static void dump_tlb(int first, int last)
        s_pagemask = read_c0_pagemask();
        s_entryhi = read_c0_entryhi();
        s_index = read_c0_index();
-       asid = s_entryhi & 0xff;
+       asid = s_entryhi & asidmask;
+       if (cpu_has_guestid)
+               s_guestctl1 = read_c0_guestctl1();
 
        for (i = first; i <= last; i++) {
                write_c0_index(i);
@@ -97,6 +104,8 @@ static void dump_tlb(int first, int last)
                entryhi  = read_c0_entryhi();
                entrylo0 = read_c0_entrylo0();
                entrylo1 = read_c0_entrylo1();
+               if (cpu_has_guestid)
+                       guestctl1 = read_c0_guestctl1();
 
                /* EHINV bit marks entire entry as invalid */
                if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV)
@@ -115,7 +124,7 @@ static void dump_tlb(int first, int last)
                 * due to duplicate TLB entry.
                 */
                if (!((entrylo0 | entrylo1) & ENTRYLO_G) &&
-                   (entryhi & 0xff) != asid)
+                   (entryhi & asidmask) != asid)
                        continue;
 
                /*
@@ -126,15 +135,19 @@ static void dump_tlb(int first, int last)
                c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
                c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
 
-               printk("va=%0*lx asid=%02lx\n",
+               printk("va=%0*lx asid=%0*lx",
                       vwidth, (entryhi & ~0x1fffUL),
-                      entryhi & 0xff);
+                      asidwidth, entryhi & asidmask);
+               if (cpu_has_guestid)
+                       printk(" gid=%02lx",
+                              (guestctl1 & MIPS_GCTL1_RID)
+                                       >> MIPS_GCTL1_RID_SHIFT);
                /* RI/XI are in awkward places, so mask them off separately */
                pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
                if (xpa)
                        pa |= (unsigned long long)readx_c0_entrylo0() << 30;
                pa = (pa << 6) & PAGE_MASK;
-               printk("\t[");
+               printk("\n\t[");
                if (cpu_has_rixi)
                        printk("ri=%d xi=%d ",
                               (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0,
@@ -164,6 +177,8 @@ static void dump_tlb(int first, int last)
        write_c0_entryhi(s_entryhi);
        write_c0_index(s_index);
        write_c0_pagemask(s_pagemask);
+       if (cpu_has_guestid)
+               write_c0_guestctl1(s_guestctl1);
 }
 
 void dump_tlb_all(void)
index 8f0019a2e5c84bcd4f439559dad479b44903269a..18a1ccd4d1348c0134ed9d755512b66d1f54779d 100644 (file)
        .hidden __memset
        .endif
 
+#ifdef CONFIG_CPU_MIPSR6
 .Lbyte_fixup\@:
        PTR_SUBU        a2, $0, t0
        jr              ra
         PTR_ADDIU      a2, 1
+#endif /* CONFIG_CPU_MIPSR6 */
 
 .Lfirst_fixup\@:
        jr      ra
index cfcbb5218b5951bbfaf661f99dec5da5c710c6bf..744f4a7bc49dfa5eabbde9b78228e0d2065799d4 100644 (file)
@@ -29,9 +29,10 @@ static void dump_tlb(int first, int last)
 {
        int     i;
        unsigned int asid;
-       unsigned long entryhi, entrylo0;
+       unsigned long entryhi, entrylo0, asid_mask;
 
-       asid = read_c0_entryhi() & ASID_MASK;
+       asid_mask = cpu_asid_mask(&current_cpu_data);
+       asid = read_c0_entryhi() & asid_mask;
 
        for (i = first; i <= last; i++) {
                write_c0_index(i<<8);
@@ -46,7 +47,7 @@ static void dump_tlb(int first, int last)
                /* Unused entries have a virtual address of KSEG0.  */
                if ((entryhi & PAGE_MASK) != KSEG0 &&
                    (entrylo0 & R3K_ENTRYLO_G ||
-                    (entryhi & ASID_MASK) == asid)) {
+                    (entryhi & asid_mask) == asid)) {
                        /*
                         * Only print entries in use
                         */
@@ -55,7 +56,7 @@ static void dump_tlb(int first, int last)
                        printk("va=%08lx asid=%08lx"
                               "  [pa=%06lx n=%d d=%d v=%d g=%d]",
                               entryhi & PAGE_MASK,
-                              entryhi & ASID_MASK,
+                              entryhi & asid_mask,
                               entrylo0 & PAGE_MASK,
                               (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0,
                               (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0,
index ddf1d4cbf31e915c59f5a8e0484452285844d6a1..f2c714d8fb60c7654274cd1e1ee604954a86e6c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.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
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
+#include <linux/mtd/partitions.h>
+#include <linux/sizes.h>
 #include <linux/phy.h>
 #include <linux/serial_8250.h>
 #include <linux/stmmac.h>
 #include <linux/usb/ehci_pdriver.h>
-#include <asm-generic/sizes.h>
 
-#include <cpufreq.h>
 #include <loongson1.h>
+#include <cpufreq.h>
+#include <dma.h>
+#include <nand.h>
 
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id)                                         \
@@ -45,7 +48,7 @@ struct platform_device ls1x_uart_pdev = {
        },
 };
 
-void __init ls1x_serial_setup(struct platform_device *pdev)
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev)
 {
        struct clk *clk;
        struct plat_serial8250_port *p;
@@ -77,6 +80,42 @@ struct platform_device ls1x_cpufreq_pdev = {
        },
 };
 
+/* DMA */
+static struct resource ls1x_dma_resources[] = {
+       [0] = {
+               .start = LS1X_DMAC_BASE,
+               .end = LS1X_DMAC_BASE + SZ_4 - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = LS1X_DMA0_IRQ,
+               .end = LS1X_DMA0_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start = LS1X_DMA1_IRQ,
+               .end = LS1X_DMA1_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       [3] = {
+               .start = LS1X_DMA2_IRQ,
+               .end = LS1X_DMA2_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device ls1x_dma_pdev = {
+       .name           = "ls1x-dma",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(ls1x_dma_resources),
+       .resource       = ls1x_dma_resources,
+};
+
+void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata)
+{
+       ls1x_dma_pdev.dev.platform_data = pdata;
+}
+
 /* Synopsys Ethernet GMAC */
 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
        .phy_mask       = 0,
@@ -198,6 +237,64 @@ struct platform_device ls1x_eth1_pdev = {
        },
 };
 
+/* GPIO */
+static struct resource ls1x_gpio0_resources[] = {
+       [0] = {
+               .start  = LS1X_GPIO0_BASE,
+               .end    = LS1X_GPIO0_BASE + SZ_4 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+struct platform_device ls1x_gpio0_pdev = {
+       .name           = "ls1x-gpio",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(ls1x_gpio0_resources),
+       .resource       = ls1x_gpio0_resources,
+};
+
+static struct resource ls1x_gpio1_resources[] = {
+       [0] = {
+               .start  = LS1X_GPIO1_BASE,
+               .end    = LS1X_GPIO1_BASE + SZ_4 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+struct platform_device ls1x_gpio1_pdev = {
+       .name           = "ls1x-gpio",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(ls1x_gpio1_resources),
+       .resource       = ls1x_gpio1_resources,
+};
+
+/* NAND Flash */
+static struct resource ls1x_nand_resources[] = {
+       [0] = {
+               .start  = LS1X_NAND_BASE,
+               .end    = LS1X_NAND_BASE + SZ_32 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* DMA channel 0 is dedicated to NAND */
+               .start  = LS1X_DMA_CHANNEL0,
+               .end    = LS1X_DMA_CHANNEL0,
+               .flags  = IORESOURCE_DMA,
+       },
+};
+
+struct platform_device ls1x_nand_pdev = {
+       .name           = "ls1x-nand",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(ls1x_nand_resources),
+       .resource       = ls1x_nand_resources,
+};
+
+void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata)
+{
+       ls1x_nand_pdev.dev.platform_data = pdata;
+}
+
 /* USB EHCI */
 static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
 
index c41e4ca56ab487f11f9186c98d0b6182bdda59d7..8a1d9cc5a134356910815c736f356821c8c77ec5 100644 (file)
@@ -9,12 +9,13 @@
 
 #include <linux/io.h>
 #include <linux/pm.h>
+#include <linux/sizes.h>
 #include <asm/idle.h>
 #include <asm/reboot.h>
 
 #include <loongson1.h>
 
-static void __iomem *wdt_base;
+static void __iomem *wdt_reg_base;
 
 static void ls1x_halt(void)
 {
@@ -26,9 +27,9 @@ static void ls1x_halt(void)
 
 static void ls1x_restart(char *command)
 {
-       __raw_writel(0x1, wdt_base + WDT_EN);
-       __raw_writel(0x1, wdt_base + WDT_TIMER);
-       __raw_writel(0x1, wdt_base + WDT_SET);
+       __raw_writel(0x1, wdt_reg_base + WDT_EN);
+       __raw_writel(0x1, wdt_reg_base + WDT_TIMER);
+       __raw_writel(0x1, wdt_reg_base + WDT_SET);
 
        ls1x_halt();
 }
@@ -40,8 +41,8 @@ static void ls1x_power_off(void)
 
 static int __init ls1x_reboot_setup(void)
 {
-       wdt_base = ioremap_nocache(LS1X_WDT_BASE, 0x0f);
-       if (!wdt_base)
+       wdt_reg_base = ioremap_nocache(LS1X_WDT_BASE, (SZ_4 + SZ_8));
+       if (!wdt_reg_base)
                panic("Failed to remap watchdog registers");
 
        _machine_restart = ls1x_restart;
index 0996b025eeefb0e6aee1081bd0360e6ff0d53b29..ff224f0020e504da5e45f6c0e0264eba526b1669 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/clk.h>
 #include <linux/interrupt.h>
+#include <linux/sizes.h>
 #include <asm/time.h>
 
 #include <loongson1.h>
 
 DEFINE_RAW_SPINLOCK(ls1x_timer_lock);
 
-static void __iomem *timer_base;
+static void __iomem *timer_reg_base;
 static uint32_t ls1x_jiffies_per_tick;
 
 static inline void ls1x_pwmtimer_set_period(uint32_t period)
 {
-       __raw_writel(period, timer_base + PWM_HRC);
-       __raw_writel(period, timer_base + PWM_LRC);
+       __raw_writel(period, timer_reg_base + PWM_HRC);
+       __raw_writel(period, timer_reg_base + PWM_LRC);
 }
 
 static inline void ls1x_pwmtimer_restart(void)
 {
-       __raw_writel(0x0, timer_base + PWM_CNT);
-       __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+       __raw_writel(0x0, timer_reg_base + PWM_CNT);
+       __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL);
 }
 
 void __init ls1x_pwmtimer_init(void)
 {
-       timer_base = ioremap(LS1X_TIMER_BASE, 0xf);
-       if (!timer_base)
+       timer_reg_base = ioremap_nocache(LS1X_TIMER_BASE, SZ_16);
+       if (!timer_reg_base)
                panic("Failed to remap timer registers");
 
        ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ);
@@ -86,7 +87,7 @@ static cycle_t ls1x_clocksource_read(struct clocksource *cs)
         */
        jifs = jiffies;
        /* read the count */
-       count = __raw_readl(timer_base + PWM_CNT);
+       count = __raw_readl(timer_reg_base + PWM_CNT);
 
        /*
         * It's possible for count to appear to go the wrong way for this
@@ -131,7 +132,7 @@ static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd)
        raw_spin_lock(&ls1x_timer_lock);
        ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick);
        ls1x_pwmtimer_restart();
-       __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+       __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL);
        raw_spin_unlock(&ls1x_timer_lock);
 
        return 0;
@@ -140,7 +141,7 @@ static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd)
 static int ls1x_clockevent_tick_resume(struct clock_event_device *cd)
 {
        raw_spin_lock(&ls1x_timer_lock);
-       __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+       __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL);
        raw_spin_unlock(&ls1x_timer_lock);
 
        return 0;
@@ -149,8 +150,8 @@ static int ls1x_clockevent_tick_resume(struct clock_event_device *cd)
 static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd)
 {
        raw_spin_lock(&ls1x_timer_lock);
-       __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN,
-                    timer_base + PWM_CTRL);
+       __raw_writel(__raw_readl(timer_reg_base + PWM_CTRL) & ~CNT_EN,
+                    timer_reg_base + PWM_CTRL);
        raw_spin_unlock(&ls1x_timer_lock);
 
        return 0;
@@ -220,7 +221,7 @@ void __init plat_time_init(void)
 
 #ifdef CONFIG_CEVT_CSRC_LS1X
        /* setup LS1X PWM timer */
-       clk = clk_get(NULL, "ls1x_pwmtimer");
+       clk = clk_get(NULL, "ls1x-pwmtimer");
        if (IS_ERR(clk))
                panic("unable to get timer clock, err=%ld", PTR_ERR(clk));
 
index 58daeea25739c7bbba442d8c885e588b5b4632ce..38a1d404be1b0268a3700ffbb304897b378668b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.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
@@ -7,26 +7,83 @@
  * option) any later version.
  */
 
+#include <linux/leds.h>
+#include <linux/mtd/partitions.h>
+#include <linux/sizes.h>
+
+#include <loongson1.h>
+#include <dma.h>
+#include <nand.h>
 #include <platform.h>
 
+struct plat_ls1x_dma ls1x_dma_pdata = {
+       .nr_channels    = 3,
+};
+
+static struct mtd_partition ls1x_nand_parts[] = {
+       {
+               .name        = "kernel",
+               .offset      = 0,
+               .size        = SZ_16M,
+       },
+       {
+               .name        = "rootfs",
+               .offset      = MTDPART_OFS_APPEND,
+               .size        = MTDPART_SIZ_FULL,
+       },
+};
+
+struct plat_ls1x_nand ls1x_nand_pdata = {
+       .parts          = ls1x_nand_parts,
+       .nr_parts       = ARRAY_SIZE(ls1x_nand_parts),
+       .hold_cycle     = 0x2,
+       .wait_cycle     = 0xc,
+};
+
+static const struct gpio_led ls1x_gpio_leds[] __initconst = {
+       {
+               .name                   = "LED9",
+               .default_trigger        = "heartbeat",
+               .gpio                   = 38,
+               .active_low             = 1,
+               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
+       }, {
+               .name                   = "LED6",
+               .default_trigger        = "nand-disk",
+               .gpio                   = 39,
+               .active_low             = 1,
+               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
+       },
+};
+
+static const struct gpio_led_platform_data ls1x_led_pdata __initconst = {
+       .num_leds       = ARRAY_SIZE(ls1x_gpio_leds),
+       .leds           = ls1x_gpio_leds,
+};
+
 static struct platform_device *ls1b_platform_devices[] __initdata = {
        &ls1x_uart_pdev,
        &ls1x_cpufreq_pdev,
+       &ls1x_dma_pdev,
        &ls1x_eth0_pdev,
        &ls1x_eth1_pdev,
        &ls1x_ehci_pdev,
+       &ls1x_gpio0_pdev,
+       &ls1x_gpio1_pdev,
+       &ls1x_nand_pdev,
        &ls1x_rtc_pdev,
 };
 
 static int __init ls1b_platform_init(void)
 {
-       int err;
+       ls1x_serial_set_uartclk(&ls1x_uart_pdev);
+       ls1x_dma_set_platdata(&ls1x_dma_pdata);
+       ls1x_nand_set_platdata(&ls1x_nand_pdata);
 
-       ls1x_serial_setup(&ls1x_uart_pdev);
+       gpio_led_register_device(-1, &ls1x_led_pdata);
 
-       err = platform_add_devices(ls1b_platform_devices,
+       return platform_add_devices(ls1b_platform_devices,
                                   ARRAY_SIZE(ls1b_platform_devices));
-       return err;
 }
 
 arch_initcall(ls1b_platform_init);
index 85d808924c94b52b25f24654def7529b76039266..0fce4608aa88665febfcad2964690beff5000a0d 100644 (file)
@@ -31,7 +31,7 @@ cflags-$(CONFIG_CPU_LOONGSON3)        += -Wa,--trap
 # can't easily be used safely within the kbuild framework.
 #
 ifeq ($(call cc-ifversion, -ge, 0409, y), y)
-  ifeq ($(call ld-ifversion, -ge, 22500000, y), y)
+  ifeq ($(call ld-ifversion, -ge, 225000000, y), y)
     cflags-$(CONFIG_CPU_LOONGSON3)  += \
       $(call cc-option,-march=loongson3a -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64)
   else
index d6d07ad56180fa7438595994833aef5e60628350..57d590ac80045b9bf9848a6e216d22d72cff33d9 100644 (file)
@@ -105,6 +105,10 @@ void __init prom_init_env(void)
                loongson_chiptemp[1] = 0x900010001fe0019c;
                loongson_chiptemp[2] = 0x900020001fe0019c;
                loongson_chiptemp[3] = 0x900030001fe0019c;
+               loongson_freqctrl[0] = 0x900000001fe001d0;
+               loongson_freqctrl[1] = 0x900010001fe001d0;
+               loongson_freqctrl[2] = 0x900020001fe001d0;
+               loongson_freqctrl[3] = 0x900030001fe001d0;
                loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
                loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
        } else if (ecpu->cputype == Loongson_3B) {
@@ -187,7 +191,8 @@ void __init prom_init_env(void)
                case PRID_REV_LOONGSON2F:
                        cpu_clock_freq = 797000000;
                        break;
-               case PRID_REV_LOONGSON3A:
+               case PRID_REV_LOONGSON3A_R1:
+               case PRID_REV_LOONGSON3A_R2:
                        cpu_clock_freq = 900000000;
                        break;
                case PRID_REV_LOONGSON3B_R1:
index 622fead5ebc9b1fa22003066ab9138518b2a9d1b..44bc1482158bf2b335b3784bafb87f5cda7ba6a1 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for Loongson-3 family machines
 #
-obj-y                  += irq.o cop2-ex.o platform.o
+obj-y                  += irq.o cop2-ex.o platform.o acpi_init.o
 
 obj-$(CONFIG_SMP)      += smp.o
 
index 0f75b6b3d2184b2cf0a85e59037aa6ad589b1f6d..8e7649088353d61c103bc5f19857eba2aef281e6 100644 (file)
@@ -24,19 +24,21 @@ static void ht_irqdispatch(void)
        }
 }
 
+#define UNUSED_IPS (CAUSEF_IP5 | CAUSEF_IP4 | CAUSEF_IP1 | CAUSEF_IP0)
+
 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)
+       if (pending & CAUSEF_IP6)
                loongson3_ipi_interrupt(NULL);
 #endif
-       else if (pending & CAUSEF_IP3)
+       if (pending & CAUSEF_IP3)
                ht_irqdispatch();
-       else if (pending & CAUSEF_IP2)
+       if (pending & CAUSEF_IP2)
                do_IRQ(LOONGSON_UART_IRQ);
-       else {
+       if (pending & UNUSED_IPS) {
                pr_err("%s : spurious interrupt\n", __func__);
                spurious_interrupt();
        }
index 6f9e010cec4d50f2cae8177c41d9ae95e0189b22..282c5a8c2fcd4c22649bea11219ec7665f67602f 100644 (file)
@@ -213,10 +213,10 @@ static void __init node_mem_init(unsigned int node)
                BOOTMEM_DEFAULT);
 
        if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
-               /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+               /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */
                reserve_bootmem_node(NODE_DATA(node),
-                               (node_addrspace_offset | 0xff800000),
-                               8 << 20, BOOTMEM_DEFAULT);
+                               (node_addrspace_offset | 0xfe000000),
+                               32 << 20, BOOTMEM_DEFAULT);
        }
 
        sparse_memory_present_with_active_regions(node);
index 509832a9836c9ae70f52aa422ab70f85d7f8971c..e59759af63d9f0c929e4635e5e3993e299254e89 100644 (file)
@@ -421,7 +421,6 @@ static int loongson3_cpu_disable(void)
        local_irq_save(flags);
        fixup_irqs();
        local_irq_restore(flags);
-       flush_cache_all();
        local_flush_tlb_all();
 
        return 0;
@@ -440,7 +439,7 @@ static void loongson3_cpu_die(unsigned int cpu)
  * flush all L1 entries at first. Then, another core (usually Core 0) can
  * safely disable the clock of the target core. loongson3_play_dead() is
  * called via CKSEG1 (uncached and unmmaped) */
-static void loongson3a_play_dead(int *state_addr)
+static void loongson3a_r1_play_dead(int *state_addr)
 {
        register int val;
        register long cpuid, core, node, count;
@@ -502,6 +501,89 @@ static void loongson3a_play_dead(int *state_addr)
                : "a1");
 }
 
+static void loongson3a_r2_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], 0x40  \n"
+               "   li %[addr], 0x80000000        \n" /* KSEG0 */
+               "2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
+               "   cache 2, 1(%[addr])           \n"
+               "   cache 2, 2(%[addr])           \n"
+               "   cache 2, 3(%[addr])           \n"
+               "   cache 2, 4(%[addr])           \n"
+               "   cache 2, 5(%[addr])           \n"
+               "   cache 2, 6(%[addr])           \n"
+               "   cache 2, 7(%[addr])           \n"
+               "   cache 2, 8(%[addr])           \n"
+               "   cache 2, 9(%[addr])           \n"
+               "   cache 2, 10(%[addr])          \n"
+               "   cache 2, 11(%[addr])          \n"
+               "   cache 2, 12(%[addr])          \n"
+               "   cache 2, 13(%[addr])          \n"
+               "   cache 2, 14(%[addr])          \n"
+               "   cache 2, 15(%[addr])          \n"
+               "   addiu %[vsets], %[vsets], -1  \n"
+               "   bnez  %[vsets], 2b            \n"
+               "   addiu %[addr], %[addr], 0x40  \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),
+                 [vsets] "r" (cpu_data[smp_processor_id()].vcache.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");
+}
+
 static void loongson3b_play_dead(int *state_addr)
 {
        register int val;
@@ -573,13 +655,18 @@ void play_dead(void)
        void (*play_dead_at_ckseg1)(int *);
 
        idle_task_exit();
-       switch (loongson_sysconf.cputype) {
-       case Loongson_3A:
+       switch (read_c0_prid() & PRID_REV_MASK) {
+       case PRID_REV_LOONGSON3A_R1:
        default:
                play_dead_at_ckseg1 =
-                       (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
+                       (void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
+               break;
+       case PRID_REV_LOONGSON3A_R2:
+               play_dead_at_ckseg1 =
+                       (void *)CKSEG1ADDR((unsigned long)loongson3a_r2_play_dead);
                break;
-       case Loongson_3B:
+       case PRID_REV_LOONGSON3B_R1:
+       case PRID_REV_LOONGSON3B_R2:
                play_dead_at_ckseg1 =
                        (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
                break;
@@ -594,9 +681,9 @@ void loongson3_disable_clock(int cpu)
        uint64_t core_id = cpu_data[cpu].core;
        uint64_t package_id = cpu_data[cpu].package;
 
-       if (loongson_sysconf.cputype == Loongson_3A) {
+       if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
                LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
-       } else if (loongson_sysconf.cputype == Loongson_3B) {
+       } else {
                if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
                        LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
        }
@@ -607,9 +694,9 @@ void loongson3_enable_clock(int cpu)
        uint64_t core_id = cpu_data[cpu].core;
        uint64_t package_id = cpu_data[cpu].package;
 
-       if (loongson_sysconf.cputype == Loongson_3A) {
+       if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
                LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
-       } else if (loongson_sysconf.cputype == Loongson_3B) {
+       } else {
                if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
                        LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
        }
index a19641d3ac23cacdb327fdfaecd2b40924d0d6f5..e9bbc2a6526fa57072b0b4299ec1a230bfe01c29 100644 (file)
@@ -4,9 +4,9 @@
 
 obj-y  += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \
           dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \
-          dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o dp_2008class.o dp_fmin.o dp_fmax.o \
+          dp_tint.o dp_fint.o dp_maddf.o dp_2008class.o dp_fmin.o dp_fmax.o \
           sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \
-          sp_tint.o sp_fint.o sp_maddf.o sp_msubf.o sp_2008class.o sp_fmin.o sp_fmax.o \
+          sp_tint.o sp_fint.o sp_maddf.o sp_2008class.o sp_fmin.o sp_fmax.o \
           dsemul.o
 
 lib-y  += ieee754d.o \
index cdfd44ffa51c88133b7b59417adb3fc070dfeee7..d96e912b9d44fa7a077500e9ba884deb8caf3cbd 100644 (file)
@@ -445,9 +445,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
        case spec_op:
                switch (insn.r_format.func) {
                case jalr_op:
-                       regs->regs[insn.r_format.rd] =
-                               regs->cp0_epc + dec_insn.pc_inc +
-                               dec_insn.next_pc_inc;
+                       if (insn.r_format.rd != 0) {
+                               regs->regs[insn.r_format.rd] =
+                                       regs->cp0_epc + dec_insn.pc_inc +
+                                       dec_insn.next_pc_inc;
+                       }
                        /* Fall through */
                case jr_op:
                        /* For R6, JR already emulated in jalr_op */
@@ -973,9 +975,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                struct mm_decoded_insn dec_insn, void *__user *fault_addr)
 {
        unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc;
-       unsigned int cond, cbit;
+       unsigned int cond, cbit, bit0;
        mips_instruction ir;
        int likely, pc_inc;
+       union fpureg *fpr;
        u32 __user *wva;
        u64 __user *dva;
        u32 wval;
@@ -1187,14 +1190,14 @@ emul:
                                return SIGILL;
 
                        cond = likely = 0;
+                       fpr = &current->thread.fpu.fpr[MIPSInst_RT(ir)];
+                       bit0 = get_fpr32(fpr, 0) & 0x1;
                        switch (MIPSInst_RS(ir)) {
                        case bc1eqz_op:
-                               if (get_fpr32(&current->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1)
-                                   cond = 1;
+                               cond = bit0 == 0;
                                break;
                        case bc1nez_op:
-                               if (!(get_fpr32(&current->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1))
-                                   cond = 1;
+                               cond = bit0 != 0;
                                break;
                        }
                        goto branch_common;
@@ -1674,7 +1677,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        union ieee754sp(*b) (union ieee754sp, union ieee754sp);
                        union ieee754sp(*u) (union ieee754sp);
                } handler;
-               union ieee754sp fs, ft;
+               union ieee754sp fd, fs, ft;
 
                switch (MIPSInst_FUNC(ir)) {
                        /* binary ops */
@@ -1945,6 +1948,17 @@ copcsr:
                        rfmt = w_fmt;
                        goto copcsr;
 
+               case fsel_op:
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(fd, MIPSInst_FD(ir));
+                       if (fd.bits & 0x1)
+                               SPFROMREG(rv.s, MIPSInst_FT(ir));
+                       else
+                               SPFROMREG(rv.s, MIPSInst_FS(ir));
+                       break;
+
                case fcvtl_op:
                        if (!cpu_has_mips_3_4_5_64_r2_r6)
                                return SIGILL;
@@ -1993,7 +2007,7 @@ copcsr:
        }
 
        case d_fmt: {
-               union ieee754dp fs, ft;
+               union ieee754dp fd, fs, ft;
                union {
                        union ieee754dp(*b) (union ieee754dp, union ieee754dp);
                        union ieee754dp(*u) (union ieee754dp);
@@ -2243,6 +2257,17 @@ dcopuop:
                        rfmt = w_fmt;
                        goto copcsr;
 
+               case fsel_op:
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(fd, MIPSInst_FD(ir));
+                       if (fd.bits & 0x1)
+                               DPFROMREG(rv.d, MIPSInst_FT(ir));
+                       else
+                               DPFROMREG(rv.d, MIPSInst_FS(ir));
+                       break;
+
                case fcvtl_op:
                        if (!cpu_has_mips_3_4_5_64_r2_r6)
                                return SIGILL;
index 119eda9fa1ea8f353fded2fe03beb9bece359154..4a2d03c72959cb5f1fb67da81e9f11b143086256 100644 (file)
 
 #include "ieee754dp.h"
 
-union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
-                               union ieee754dp y)
+enum maddf_flags {
+       maddf_negate_product    = 1 << 0,
+};
+
+static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
+                                union ieee754dp y, enum maddf_flags flags)
 {
        int re;
        int rs;
@@ -32,16 +36,15 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
 
        COMPXDP;
        COMPYDP;
-
-       u64 zm; int ze; int zs __maybe_unused; int zc;
+       COMPZDP;
 
        EXPLODEXDP;
        EXPLODEYDP;
-       EXPLODEDP(z, zc, zs, ze, zm)
+       EXPLODEZDP;
 
        FLUSHXDP;
        FLUSHYDP;
-       FLUSHDP(z, zc, zs, ze, zm);
+       FLUSHZDP;
 
        ieee754_clearcx();
 
@@ -50,7 +53,7 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
                ieee754_setcx(IEEE754_INVALID_OPERATION);
                return ieee754dp_nanxcpt(z);
        case IEEE754_CLASS_DNORM:
-               DPDNORMx(zm, ze);
+               DPDNORMZ;
        /* QNAN is handled separately below */
        }
 
@@ -154,13 +157,15 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
 
        re = xe + ye;
        rs = xs ^ ys;
+       if (flags & maddf_negate_product)
+               rs ^= 1;
 
        /* shunt to top of word */
        xm <<= 64 - (DP_FBITS + 1);
        ym <<= 64 - (DP_FBITS + 1);
 
        /*
-        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+        * Multiply 64 bits xm, ym to give high 64 bits rm with stickness.
         */
 
        /* 32 * 32 => 64 */
@@ -198,7 +203,7 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
        if ((s64) rm < 0) {
                rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
                     ((rm << (DP_FBITS + 1 + 3)) != 0);
-                       re++;
+               re++;
        } else {
                rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
                     ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
@@ -263,3 +268,15 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
 
        return ieee754dp_format(zs, ze, zm);
 }
+
+union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
+                               union ieee754dp y)
+{
+       return _dp_maddf(z, x, y, 0);
+}
+
+union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
+                               union ieee754dp y)
+{
+       return _dp_maddf(z, x, y, maddf_negate_product);
+}
diff --git a/arch/mips/math-emu/dp_msubf.c b/arch/mips/math-emu/dp_msubf.c
deleted file mode 100644 (file)
index 1224126..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * IEEE754 floating point arithmetic
- * double precision: MSUB.f (Fused Multiply Subtract)
- * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
- *
- * MIPS floating point support
- * Copyright (C) 2015 Imagination Technologies, Ltd.
- * Author: Markos Chandras <markos.chandras@imgtec.com>
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; version 2 of the License.
- */
-
-#include "ieee754dp.h"
-
-union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
-                               union ieee754dp y)
-{
-       int re;
-       int rs;
-       u64 rm;
-       unsigned lxm;
-       unsigned hxm;
-       unsigned lym;
-       unsigned hym;
-       u64 lrm;
-       u64 hrm;
-       u64 t;
-       u64 at;
-       int s;
-
-       COMPXDP;
-       COMPYDP;
-
-       u64 zm; int ze; int zs __maybe_unused; int zc;
-
-       EXPLODEXDP;
-       EXPLODEYDP;
-       EXPLODEDP(z, zc, zs, ze, zm)
-
-       FLUSHXDP;
-       FLUSHYDP;
-       FLUSHDP(z, zc, zs, ze, zm);
-
-       ieee754_clearcx();
-
-       switch (zc) {
-       case IEEE754_CLASS_SNAN:
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_nanxcpt(z);
-       case IEEE754_CLASS_DNORM:
-               DPDNORMx(zm, ze);
-       /* QNAN is handled separately below */
-       }
-
-       switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
-               return ieee754dp_nanxcpt(y);
-
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               return ieee754dp_nanxcpt(x);
-
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
-               return y;
-
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
-               return x;
-
-
-       /*
-        * Infinity handling
-        */
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754dp_indef();
-
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               return ieee754dp_inf(xs ^ ys);
-
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
-               if (zc == IEEE754_CLASS_INF)
-                       return ieee754dp_inf(zs);
-               /* Multiplication is 0 so just return z */
-               return z;
-
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
-               DPDNORMX;
-
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               else if (zc == IEEE754_CLASS_INF)
-                       return ieee754dp_inf(zs);
-               DPDNORMY;
-               break;
-
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               else if (zc == IEEE754_CLASS_INF)
-                       return ieee754dp_inf(zs);
-               DPDNORMX;
-               break;
-
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               else if (zc == IEEE754_CLASS_INF)
-                       return ieee754dp_inf(zs);
-               /* fall through to real computations */
-       }
-
-       /* Finally get to do some computation */
-
-       /*
-        * Do the multiplication bit first
-        *
-        * rm = xm * ym, re = xe + ye basically
-        *
-        * At this point xm and ym should have been normalized.
-        */
-       assert(xm & DP_HIDDEN_BIT);
-       assert(ym & DP_HIDDEN_BIT);
-
-       re = xe + ye;
-       rs = xs ^ ys;
-
-       /* shunt to top of word */
-       xm <<= 64 - (DP_FBITS + 1);
-       ym <<= 64 - (DP_FBITS + 1);
-
-       /*
-        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
-        */
-
-       /* 32 * 32 => 64 */
-#define DPXMULT(x, y)  ((u64)(x) * (u64)y)
-
-       lxm = xm;
-       hxm = xm >> 32;
-       lym = ym;
-       hym = ym >> 32;
-
-       lrm = DPXMULT(lxm, lym);
-       hrm = DPXMULT(hxm, hym);
-
-       t = DPXMULT(lxm, hym);
-
-       at = lrm + (t << 32);
-       hrm += at < lrm;
-       lrm = at;
-
-       hrm = hrm + (t >> 32);
-
-       t = DPXMULT(hxm, lym);
-
-       at = lrm + (t << 32);
-       hrm += at < lrm;
-       lrm = at;
-
-       hrm = hrm + (t >> 32);
-
-       rm = hrm | (lrm != 0);
-
-       /*
-        * Sticky shift down to normal rounding precision.
-        */
-       if ((s64) rm < 0) {
-               rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
-                    ((rm << (DP_FBITS + 1 + 3)) != 0);
-                       re++;
-       } else {
-               rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
-                    ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
-       }
-       assert(rm & (DP_HIDDEN_BIT << 3));
-
-       /* And now the subtraction */
-
-       /* flip sign of r and handle as add */
-       rs ^= 1;
-
-       assert(zm & DP_HIDDEN_BIT);
-
-       /*
-        * Provide guard,round and stick bit space.
-        */
-       zm <<= 3;
-
-       if (ze > re) {
-               /*
-                * Have to shift y fraction right to align.
-                */
-               s = ze - re;
-               rm = XDPSRS(rm, s);
-               re += s;
-       } else if (re > ze) {
-               /*
-                * Have to shift x fraction right to align.
-                */
-               s = re - ze;
-               zm = XDPSRS(zm, s);
-               ze += s;
-       }
-       assert(ze == re);
-       assert(ze <= DP_EMAX);
-
-       if (zs == rs) {
-               /*
-                * Generate 28 bit result of adding two 27 bit numbers
-                * leaving result in xm, xs and xe.
-                */
-               zm = zm + rm;
-
-               if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
-                       zm = XDPSRS1(zm);
-                       ze++;
-               }
-       } else {
-               if (zm >= rm) {
-                       zm = zm - rm;
-               } else {
-                       zm = rm - zm;
-                       zs = rs;
-               }
-               if (zm == 0)
-                       return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
-
-               /*
-                * Normalize to rounding precision.
-                */
-               while ((zm >> (DP_FBITS + 3)) == 0) {
-                       zm <<= 1;
-                       ze--;
-               }
-       }
-
-       return ieee754dp_format(zs, ze, zm);
-}
index d0901f03fa197c30a979ec3b560ba5bfa0244902..87d0b44b0614767e6070ae4de41aa8de76409e8a 100644 (file)
@@ -125,7 +125,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)
        ym <<= 64 - (DP_FBITS + 1);
 
        /*
-        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+        * Multiply 64 bits xm, ym to give high 64 bits rm with stickness.
         */
 
        /* 32 * 32 => 64 */
@@ -163,7 +163,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)
        if ((s64) rm < 0) {
                rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
                     ((rm << (DP_FBITS + 1 + 3)) != 0);
-                       re++;
+               re++;
        } else {
                rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
                     ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
index 46b964d2b79c0a0f24aa7cf6e77e1846a88e842f..d4ceacd4fa1282b06cf1cef7d494e5c2731e611b 100644 (file)
@@ -60,7 +60,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
                        unsigned int rs;
                        s32 v;
 
-                       rs = (((insn.mm_a_format.rs + 0x1e) & 0xf) + 2);
+                       rs = (((insn.mm_a_format.rs + 0xe) & 0xf) + 2);
                        v = regs->cp0_epc & ~3;
                        v += insn.mm_a_format.simmediate << 2;
                        regs->regs[rs] = (long)v;
index 47d26c805eac5b4f91d600eee67075ed980ab250..465a0342ed4c8ca8028420299ae374952870c63f 100644 (file)
@@ -54,10 +54,13 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)
        assert(ieee754dp_issnan(r));
 
        ieee754_setcx(IEEE754_INVALID_OPERATION);
-       if (ieee754_csr.nan2008)
+       if (ieee754_csr.nan2008) {
                DPMANT(r) |= DP_MBIT(DP_FBITS - 1);
-       else
-               r = ieee754dp_indef();
+       } else {
+               DPMANT(r) &= ~DP_MBIT(DP_FBITS - 1);
+               if (!ieee754dp_isnan(r))
+                       DPMANT(r) |= DP_MBIT(DP_FBITS - 2);
+       }
 
        return r;
 }
index e2babd98fee3014c05e6544b2c6438eacf282f51..9ba023004eb6ff7f03a796a3acae8b609e3faea6 100644 (file)
@@ -60,6 +60,7 @@ static inline int ieee754dp_finite(union ieee754dp x)
        while ((m >> DP_FBITS) == 0) { m <<= 1; e--; }
 #define DPDNORMX       DPDNORMx(xm, xe)
 #define DPDNORMY       DPDNORMx(ym, ye)
+#define DPDNORMZ       DPDNORMx(zm, ze)
 
 static inline union ieee754dp builddp(int s, int bx, u64 m)
 {
index ed7bb277b3e05e224315508f32396fd37c239641..8bc2f6963324de776a3ab66ec33638e2b8598211 100644 (file)
@@ -55,6 +55,9 @@ static inline int ieee754_class_nan(int xc)
 #define COMPYSP \
        unsigned ym; int ye; int ys; int yc
 
+#define COMPZSP \
+       unsigned zm; int ze; int zs; int zc
+
 #define EXPLODESP(v, vc, vs, ve, vm)                                   \
 {                                                                      \
        vs = SPSIGN(v);                                                 \
@@ -81,6 +84,7 @@ static inline int ieee754_class_nan(int xc)
 }
 #define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm)
 #define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym)
+#define EXPLODEZSP EXPLODESP(z, zc, zs, ze, zm)
 
 
 #define COMPXDP \
@@ -89,6 +93,9 @@ static inline int ieee754_class_nan(int xc)
 #define COMPYDP \
        u64 ym; int ye; int ys; int yc
 
+#define COMPZDP \
+       u64 zm; int ze; int zs; int zc
+
 #define EXPLODEDP(v, vc, vs, ve, vm)                                   \
 {                                                                      \
        vm = DPMANT(v);                                                 \
@@ -115,6 +122,7 @@ static inline int ieee754_class_nan(int xc)
 }
 #define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm)
 #define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym)
+#define EXPLODEZDP EXPLODEDP(z, zc, zs, ze, zm)
 
 #define FLUSHDP(v, vc, vs, ve, vm)                                     \
        if (vc==IEEE754_CLASS_DNORM) {                                  \
@@ -140,7 +148,9 @@ static inline int ieee754_class_nan(int xc)
 
 #define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm)
 #define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym)
+#define FLUSHZDP FLUSHDP(z, zc, zs, ze, zm)
 #define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm)
 #define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym)
+#define FLUSHZSP FLUSHSP(z, zc, zs, ze, zm)
 
 #endif /* __IEEE754INT_H  */
index e0b2c450b9634caadcd24d5a25d3f58d4ad2f805..260e68965907283b7f6ef8286f0bbd0f4fc3ad43 100644 (file)
@@ -54,10 +54,13 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
        assert(ieee754sp_issnan(r));
 
        ieee754_setcx(IEEE754_INVALID_OPERATION);
-       if (ieee754_csr.nan2008)
+       if (ieee754_csr.nan2008) {
                SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
-       else
-               r = ieee754sp_indef();
+       } else {
+               SPMANT(r) &= ~SP_MBIT(SP_FBITS - 1);
+               if (!ieee754sp_isnan(r))
+                       SPMANT(r) |= SP_MBIT(SP_FBITS - 2);
+       }
 
        return r;
 }
@@ -138,7 +141,8 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
                } else {
                        /* sticky right shift es bits
                         */
-                       SPXSRSXn(es);
+                       xm = XSPSRS(xm, es);
+                       xe += es;
                        assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
                        assert(xe == SP_EMIN);
                }
index 374a3f00a589b5c8d92db80fce1729edb9426130..8476067075fe013331609ed3db1028b04b9d3e66 100644 (file)
@@ -46,25 +46,24 @@ static inline int ieee754sp_finite(union ieee754sp x)
 }
 
 /* 3bit extended single precision sticky right shift */
-#define SPXSRSXn(rs)                                                   \
-       (xe += rs,                                                      \
-        xm = (rs > (SP_FBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+#define XSPSRS(v, rs)                                          \
+       ((rs > (SP_FBITS+3))?1:((v) >> (rs)) | ((v) << (32-(rs)) != 0))
 
-#define SPXSRSX1() \
-       (xe++, (xm = (xm >> 1) | (xm & 1)))
+#define XSPSRS1(m) \
+       ((m >> 1) | (m & 1))
 
-#define SPXSRSYn(rs)                                                           \
-       (ye+=rs,                                                                \
-        ym = (rs > (SP_FBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+#define SPXSRSX1() \
+       (xe++, (xm = XSPSRS1(xm)))
 
 #define SPXSRSY1() \
-       (ye++, (ym = (ym >> 1) | (ym & 1)))
+       (ye++, (ym = XSPSRS1(ym)))
 
 /* convert denormal to normalized with extended exponent */
 #define SPDNORMx(m,e) \
        while ((m >> SP_FBITS) == 0) { m <<= 1; e--; }
 #define SPDNORMX       SPDNORMx(xm, xe)
 #define SPDNORMY       SPDNORMx(ym, ye)
+#define SPDNORMZ       SPDNORMx(zm, ze)
 
 static inline union ieee754sp buildsp(int s, int bx, unsigned m)
 {
index f1c87b07d3b4758167628bb087fc21124c8c5f51..c55c0c00bca803b989825397aedb915f28359402 100644 (file)
@@ -132,13 +132,15 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
                 * Have to shift y fraction right to align.
                 */
                s = xe - ye;
-               SPXSRSYn(s);
+               ym = XSPSRS(ym, s);
+               ye += s;
        } else if (ye > xe) {
                /*
                 * Have to shift x fraction right to align.
                 */
                s = ye - xe;
-               SPXSRSXn(s);
+               xm = XSPSRS(xm, s);
+               xe += s;
        }
        assert(xe == ye);
        assert(xe <= SP_EMAX);
index dd1dd83e34eb0ba604a2b88c9e4db20c96174d8c..a8cd8b4f235eb810db8c0472dea29c82dc2cd173 100644 (file)
 
 #include "ieee754sp.h"
 
-union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
-                               union ieee754sp y)
+enum maddf_flags {
+       maddf_negate_product    = 1 << 0,
+};
+
+static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
+                                union ieee754sp y, enum maddf_flags flags)
 {
        int re;
        int rs;
@@ -32,15 +36,15 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
 
        COMPXSP;
        COMPYSP;
-       u32 zm; int ze; int zs __maybe_unused; int zc;
+       COMPZSP;
 
        EXPLODEXSP;
        EXPLODEYSP;
-       EXPLODESP(z, zc, zs, ze, zm)
+       EXPLODEZSP;
 
        FLUSHXSP;
        FLUSHYSP;
-       FLUSHSP(z, zc, zs, ze, zm);
+       FLUSHZSP;
 
        ieee754_clearcx();
 
@@ -49,7 +53,7 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
                ieee754_setcx(IEEE754_INVALID_OPERATION);
                return ieee754sp_nanxcpt(z);
        case IEEE754_CLASS_DNORM:
-               SPDNORMx(zm, ze);
+               SPDNORMZ;
        /* QNAN is handled separately below */
        }
 
@@ -154,6 +158,8 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
 
        re = xe + ye;
        rs = xs ^ ys;
+       if (flags & maddf_negate_product)
+               rs ^= 1;
 
        /* shunt to top of word */
        xm <<= 32 - (SP_FBITS + 1);
@@ -208,16 +214,18 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
 
        if (ze > re) {
                /*
-                * Have to shift y fraction right to align.
+                * Have to shift r fraction right to align.
                 */
                s = ze - re;
-               SPXSRSYn(s);
+               rm = XSPSRS(rm, s);
+               re += s;
        } else if (re > ze) {
                /*
-                * Have to shift x fraction right to align.
+                * Have to shift z fraction right to align.
                 */
                s = re - ze;
-               SPXSRSYn(s);
+               zm = XSPSRS(zm, s);
+               ze += s;
        }
        assert(ze == re);
        assert(ze <= SP_EMAX);
@@ -230,7 +238,8 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
                zm = zm + rm;
 
                if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
-                       SPXSRSX1();
+                       zm = XSPSRS1(zm);
+                       ze++;
                }
        } else {
                if (zm >= rm) {
@@ -253,3 +262,15 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
        }
        return ieee754sp_format(zs, ze, zm);
 }
+
+union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
+                               union ieee754sp y)
+{
+       return _sp_maddf(z, x, y, 0);
+}
+
+union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
+                               union ieee754sp y)
+{
+       return _sp_maddf(z, x, y, maddf_negate_product);
+}
diff --git a/arch/mips/math-emu/sp_msubf.c b/arch/mips/math-emu/sp_msubf.c
deleted file mode 100644 (file)
index 81c38b9..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * IEEE754 floating point arithmetic
- * single precision: MSUB.f (Fused Multiply Subtract)
- * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
- *
- * MIPS floating point support
- * Copyright (C) 2015 Imagination Technologies, Ltd.
- * Author: Markos Chandras <markos.chandras@imgtec.com>
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; version 2 of the License.
- */
-
-#include "ieee754sp.h"
-
-union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
-                               union ieee754sp y)
-{
-       int re;
-       int rs;
-       unsigned rm;
-       unsigned short lxm;
-       unsigned short hxm;
-       unsigned short lym;
-       unsigned short hym;
-       unsigned lrm;
-       unsigned hrm;
-       unsigned t;
-       unsigned at;
-       int s;
-
-       COMPXSP;
-       COMPYSP;
-       u32 zm; int ze; int zs __maybe_unused; int zc;
-
-       EXPLODEXSP;
-       EXPLODEYSP;
-       EXPLODESP(z, zc, zs, ze, zm)
-
-       FLUSHXSP;
-       FLUSHYSP;
-       FLUSHSP(z, zc, zs, ze, zm);
-
-       ieee754_clearcx();
-
-       switch (zc) {
-       case IEEE754_CLASS_SNAN:
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_nanxcpt(z);
-       case IEEE754_CLASS_DNORM:
-               SPDNORMx(zm, ze);
-       /* QNAN is handled separately below */
-       }
-
-       switch (CLPAIR(xc, yc)) {
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
-               return ieee754sp_nanxcpt(y);
-
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-               return ieee754sp_nanxcpt(x);
-
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
-               return y;
-
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
-               return x;
-
-       /*
-        * Infinity handling
-        */
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               ieee754_setcx(IEEE754_INVALID_OPERATION);
-               return ieee754sp_indef();
-
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               return ieee754sp_inf(xs ^ ys);
-
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
-       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
-               if (zc == IEEE754_CLASS_INF)
-                       return ieee754sp_inf(zs);
-               /* Multiplication is 0 so just return z */
-               return z;
-
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
-               SPDNORMX;
-
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               else if (zc == IEEE754_CLASS_INF)
-                       return ieee754sp_inf(zs);
-               SPDNORMY;
-               break;
-
-       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               else if (zc == IEEE754_CLASS_INF)
-                       return ieee754sp_inf(zs);
-               SPDNORMX;
-               break;
-
-       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
-               if (zc == IEEE754_CLASS_QNAN)
-                       return z;
-               else if (zc == IEEE754_CLASS_INF)
-                       return ieee754sp_inf(zs);
-               /* fall through to real compuation */
-       }
-
-       /* Finally get to do some computation */
-
-       /*
-        * Do the multiplication bit first
-        *
-        * rm = xm * ym, re = xe + ye basically
-        *
-        * At this point xm and ym should have been normalized.
-        */
-
-       /* rm = xm * ym, re = xe+ye basically */
-       assert(xm & SP_HIDDEN_BIT);
-       assert(ym & SP_HIDDEN_BIT);
-
-       re = xe + ye;
-       rs = xs ^ ys;
-
-       /* shunt to top of word */
-       xm <<= 32 - (SP_FBITS + 1);
-       ym <<= 32 - (SP_FBITS + 1);
-
-       /*
-        * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
-        */
-       lxm = xm & 0xffff;
-       hxm = xm >> 16;
-       lym = ym & 0xffff;
-       hym = ym >> 16;
-
-       lrm = lxm * lym;        /* 16 * 16 => 32 */
-       hrm = hxm * hym;        /* 16 * 16 => 32 */
-
-       t = lxm * hym; /* 16 * 16 => 32 */
-       at = lrm + (t << 16);
-       hrm += at < lrm;
-       lrm = at;
-       hrm = hrm + (t >> 16);
-
-       t = hxm * lym; /* 16 * 16 => 32 */
-       at = lrm + (t << 16);
-       hrm += at < lrm;
-       lrm = at;
-       hrm = hrm + (t >> 16);
-
-       rm = hrm | (lrm != 0);
-
-       /*
-        * Sticky shift down to normal rounding precision.
-        */
-       if ((int) rm < 0) {
-               rm = (rm >> (32 - (SP_FBITS + 1 + 3))) |
-                   ((rm << (SP_FBITS + 1 + 3)) != 0);
-               re++;
-       } else {
-               rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) |
-                    ((rm << (SP_FBITS + 1 + 3 + 1)) != 0);
-       }
-       assert(rm & (SP_HIDDEN_BIT << 3));
-
-       /* And now the subtraction */
-
-       /* Flip sign of r and handle as add */
-       rs ^= 1;
-
-       assert(zm & SP_HIDDEN_BIT);
-
-       /*
-        * Provide guard,round and stick bit space.
-        */
-       zm <<= 3;
-
-       if (ze > re) {
-               /*
-                * Have to shift y fraction right to align.
-                */
-               s = ze - re;
-               SPXSRSYn(s);
-       } else if (re > ze) {
-               /*
-                * Have to shift x fraction right to align.
-                */
-               s = re - ze;
-               SPXSRSYn(s);
-       }
-       assert(ze == re);
-       assert(ze <= SP_EMAX);
-
-       if (zs == rs) {
-               /*
-                * Generate 28 bit result of adding two 27 bit numbers
-                * leaving result in zm, zs and ze.
-                */
-               zm = zm + rm;
-
-               if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
-                       SPXSRSX1(); /* shift preserving sticky */
-               }
-       } else {
-               if (zm >= rm) {
-                       zm = zm - rm;
-               } else {
-                       zm = rm - zm;
-                       zs = rs;
-               }
-               if (zm == 0)
-                       return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
-
-               /*
-                * Normalize in extended single precision
-                */
-               while ((zm >> (SP_MBITS + 3)) == 0) {
-                       zm <<= 1;
-                       ze--;
-               }
-
-       }
-       return ieee754sp_format(zs, ze, zm);
-}
index ec5f937a8b3eeb7ae1e6369bdfdb4c7f42323fd7..dc998ed47295d677ccab8c1a1ea49c3aa09e9795 100644 (file)
@@ -134,13 +134,15 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
                 * have to shift y fraction right to align
                 */
                s = xe - ye;
-               SPXSRSYn(s);
+               ym = XSPSRS(ym, s);
+               ye += s;
        } else if (ye > xe) {
                /*
                 * have to shift x fraction right to align
                 */
                s = ye - xe;
-               SPXSRSXn(s);
+               xm = XSPSRS(xm, s);
+               xe += s;
        }
        assert(xe == ye);
        assert(xe <= SP_EMAX);
index caac3d747a909dbd75d9f0935b8a67766795174c..ef7f925dd1b0285ee743587962150f1592ac22af 100644 (file)
@@ -77,6 +77,7 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
  */
 static unsigned long icache_size __read_mostly;
 static unsigned long dcache_size __read_mostly;
+static unsigned long vcache_size __read_mostly;
 static unsigned long scache_size __read_mostly;
 
 /*
@@ -447,6 +448,11 @@ static inline void local_r4k___flush_cache_all(void * args)
                r4k_blast_scache();
                break;
 
+       case CPU_BMIPS5000:
+               r4k_blast_scache();
+               __sync();
+               break;
+
        default:
                r4k_blast_dcache();
                r4k_blast_icache();
@@ -492,7 +498,14 @@ static inline void local_r4k_flush_cache_range(void * args)
        if (!(has_valid_asid(vma->vm_mm)))
                return;
 
-       r4k_blast_dcache();
+       /*
+        * If dcache can alias, we must blast it since mapping is changing.
+        * If executable, we must ensure any dirty lines are written back far
+        * enough to be visible to icache.
+        */
+       if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
+               r4k_blast_dcache();
+       /* If executable, blast stale lines from icache */
        if (exec)
                r4k_blast_icache();
 }
@@ -502,7 +515,7 @@ static void r4k_flush_cache_range(struct vm_area_struct *vma,
 {
        int exec = vma->vm_flags & VM_EXEC;
 
-       if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
+       if (cpu_has_dc_aliases || exec)
                r4k_on_each_cpu(local_r4k_flush_cache_range, vma);
 }
 
@@ -1148,6 +1161,8 @@ static void probe_pcache(void)
                                          c->dcache.ways *
                                          c->dcache.linesz;
                c->dcache.waybit = 0;
+               if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2)
+                       c->options |= MIPS_CPU_PREFETCH;
                break;
 
        case CPU_CAVIUM_OCTEON3:
@@ -1278,6 +1293,8 @@ static void probe_pcache(void)
        case CPU_M5150:
        case CPU_QEMU_GENERIC:
        case CPU_I6400:
+       case CPU_P6600:
+       case CPU_M6250:
                if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
                    (c->icache.waysize > PAGE_SIZE))
                        c->icache.flags |= MIPS_CACHE_ALIASES;
@@ -1304,7 +1321,14 @@ static void probe_pcache(void)
                break;
 
        case CPU_ALCHEMY:
+       case CPU_I6400:
+               c->icache.flags |= MIPS_CACHE_IC_F_DC;
+               break;
+
+       case CPU_BMIPS5000:
                c->icache.flags |= MIPS_CACHE_IC_F_DC;
+               /* Cache aliases are handled in hardware; allow HIGHMEM */
+               c->dcache.flags &= ~MIPS_CACHE_ALIASES;
                break;
 
        case CPU_LOONGSON2:
@@ -1328,6 +1352,31 @@ static void probe_pcache(void)
               c->dcache.linesz);
 }
 
+static void probe_vcache(void)
+{
+       struct cpuinfo_mips *c = &current_cpu_data;
+       unsigned int config2, lsize;
+
+       if (current_cpu_type() != CPU_LOONGSON3)
+               return;
+
+       config2 = read_c0_config2();
+       if ((lsize = ((config2 >> 20) & 15)))
+               c->vcache.linesz = 2 << lsize;
+       else
+               c->vcache.linesz = lsize;
+
+       c->vcache.sets = 64 << ((config2 >> 24) & 15);
+       c->vcache.ways = 1 + ((config2 >> 16) & 15);
+
+       vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz;
+
+       c->vcache.waybit = 0;
+
+       pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n",
+               vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz);
+}
+
 /*
  * If you even _breathe_ on this function, look at the gcc output and make sure
  * it does not pop things on and off the stack for the cache sizing loop that
@@ -1650,6 +1699,7 @@ void r4k_cache_init(void)
        struct cpuinfo_mips *c = &current_cpu_data;
 
        probe_pcache();
+       probe_vcache();
        setup_scache();
 
        r4k_blast_dcache_page_setup();
@@ -1671,7 +1721,7 @@ void r4k_cache_init(void)
         * This code supports virtually indexed processors and will be
         * unnecessarily inefficient on physically indexed processors.
         */
-       if (c->dcache.linesz)
+       if (c->dcache.linesz && cpu_has_dc_aliases)
                shm_align_mask = max_t( unsigned long,
                                        c->dcache.sets * c->dcache.linesz - 1,
                                        PAGE_SIZE - 1);
@@ -1744,12 +1794,24 @@ void r4k_cache_init(void)
                flush_icache_range = (void *)b5k_instruction_hazard;
                local_flush_icache_range = (void *)b5k_instruction_hazard;
 
-               /* Cache aliases are handled in hardware; allow HIGHMEM */
-               current_cpu_data.dcache.flags &= ~MIPS_CACHE_ALIASES;
 
                /* Optimization: an L2 flush implicitly flushes the L1 */
                current_cpu_data.options |= MIPS_CPU_INCLUSIVE_CACHES;
                break;
+       case CPU_LOONGSON3:
+               /* Loongson-3 maintains cache coherency by hardware */
+               __flush_cache_all       = cache_noop;
+               __flush_cache_vmap      = cache_noop;
+               __flush_cache_vunmap    = cache_noop;
+               __flush_kernel_vmap_range = (void *)cache_noop;
+               flush_cache_mm          = (void *)cache_noop;
+               flush_cache_page        = (void *)cache_noop;
+               flush_cache_range       = (void *)cache_noop;
+               flush_cache_sigtramp    = (void *)cache_noop;
+               flush_icache_all        = (void *)cache_noop;
+               flush_data_cache_page   = (void *)cache_noop;
+               local_flush_data_cache_page     = (void *)cache_noop;
+               break;
        }
 }
 
index 3f159caf6dbc902d20d2284913aea498c67cd596..bf04c6c479a4e6ec3f99a90a8d14c093c63d5b6f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
+#include <asm/highmem.h>
 #include <asm/processor.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -83,8 +84,6 @@ void __flush_dcache_page(struct page *page)
        struct address_space *mapping = page_mapping(page);
        unsigned long addr;
 
-       if (PageHighMem(page))
-               return;
        if (mapping && !mapping_mapped(mapping)) {
                SetPageDcacheDirty(page);
                return;
@@ -95,8 +94,15 @@ void __flush_dcache_page(struct page *page)
         * case is for exec env/arg pages and those are %99 certainly going to
         * get faulted into the tlb (and thus flushed) anyways.
         */
-       addr = (unsigned long) page_address(page);
+       if (PageHighMem(page))
+               addr = (unsigned long)kmap_atomic(page);
+       else
+               addr = (unsigned long)page_address(page);
+
        flush_data_cache_page(addr);
+
+       if (PageHighMem(page))
+               __kunmap_atomic((void *)addr);
 }
 
 EXPORT_SYMBOL(__flush_dcache_page);
@@ -119,33 +125,28 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr)
 
 EXPORT_SYMBOL(__flush_anon_page);
 
-void __flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
-       unsigned long addr;
-
-       if (PageHighMem(page))
-               return;
-
-       addr = (unsigned long) page_address(page);
-       flush_data_cache_page(addr);
-}
-EXPORT_SYMBOL_GPL(__flush_icache_page);
-
-void __update_cache(struct vm_area_struct *vma, unsigned long address,
-       pte_t pte)
+void __update_cache(unsigned long address, pte_t pte)
 {
        struct page *page;
        unsigned long pfn, addr;
-       int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
+       int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc;
 
        pfn = pte_pfn(pte);
        if (unlikely(!pfn_valid(pfn)))
                return;
        page = pfn_to_page(pfn);
-       if (page_mapping(page) && Page_dcache_dirty(page)) {
-               addr = (unsigned long) page_address(page);
+       if (Page_dcache_dirty(page)) {
+               if (PageHighMem(page))
+                       addr = (unsigned long)kmap_atomic(page);
+               else
+                       addr = (unsigned long)page_address(page);
+
                if (exec || pages_do_alias(addr, address & PAGE_MASK))
                        flush_data_cache_page(addr);
+
+               if (PageHighMem(page))
+                       __kunmap_atomic((void *)addr);
+
                ClearPageDcacheDirty(page);
        }
 }
index 730d394ce5f017991146084f9df53794242c970d..cb557d28cb210b48fb6e25dc658c7585c5fb4765 100644 (file)
@@ -88,19 +88,20 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
        else
 #endif
 #if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA)
-            if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
+            if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(32))
                        dma_flag = __GFP_DMA;
        else if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
                        dma_flag = __GFP_DMA32;
        else
 #endif
 #if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA)
-            if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+            if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(64))
                dma_flag = __GFP_DMA32;
        else
 #endif
 #if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
-            if (dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8))
+            if (dev == NULL ||
+                dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8))
                dma_flag = __GFP_DMA;
        else
 #endif
index 7e5fa0938c2174cefe9d5bfb0f04249626b14af1..9b58eb5fd0d57e4f9492dbacd16eda8b4aa69f10 100644 (file)
@@ -98,8 +98,10 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot)
        idx += in_interrupt() ? FIX_N_COLOURS : 0;
        vaddr = __fix_to_virt(FIX_CMAP_END - idx);
        pte = mk_pte(page, prot);
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_XPA)
        entrylo = pte_to_entrylo(pte.pte_high);
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+       entrylo = pte.pte_high;
 #else
        entrylo = pte_to_entrylo(pte_val(pte));
 #endif
@@ -110,9 +112,11 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot)
        write_c0_entrylo0(entrylo);
        write_c0_entrylo1(entrylo);
 #ifdef CONFIG_XPA
-       entrylo = (pte.pte_low & _PFNX_MASK);
-       writex_c0_entrylo0(entrylo);
-       writex_c0_entrylo1(entrylo);
+       if (cpu_has_xpa) {
+               entrylo = (pte.pte_low & _PFNX_MASK);
+               writex_c0_entrylo0(entrylo);
+               writex_c0_entrylo1(entrylo);
+       }
 #endif
        tlbidx = read_c0_wired();
        write_c0_wired(tlbidx + 1);
@@ -196,7 +200,7 @@ void copy_to_user_page(struct vm_area_struct *vma,
                if (cpu_has_dc_aliases)
                        SetPageDcacheDirty(page);
        }
-       if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc)
+       if (vma->vm_flags & VM_EXEC)
                flush_cache_page(vma, vaddr, page_to_pfn(page));
 }
 
index 885d73ffd6fb470ff237916784ef283c19b5c7eb..c41953ca6605ca347db0bbe71689fb791ef51410 100644 (file)
@@ -188,6 +188,15 @@ static void set_prefetch_parameters(void)
                        }
                        break;
 
+               case CPU_LOONGSON3:
+                       /* Loongson-3 only support the Pref_Load/Pref_Store. */
+                       pref_bias_clear_store = 128;
+                       pref_bias_copy_load = 128;
+                       pref_bias_copy_store = 128;
+                       pref_src_mode = Pref_Load;
+                       pref_dst_mode = Pref_Store;
+                       break;
+
                default:
                        pref_bias_clear_store = 128;
                        pref_bias_copy_load = 256;
index 91dec32c77b722a838ce9ca352d89ca3939fba2b..286a4d5a18843c82be783dfde6b12798d191869e 100644 (file)
@@ -141,6 +141,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
        case CPU_P5600:
        case CPU_BMIPS5000:
        case CPU_QEMU_GENERIC:
+       case CPU_P6600:
                if (config2 & (1 << 12))
                        return 0;
        }
index b4f366f7c0f57ae86a5cf601d75c81cda7ee2acd..1290b995695d45d06105cde3dce65eec4878322c 100644 (file)
@@ -43,7 +43,7 @@ static void local_flush_tlb_from(int entry)
 {
        unsigned long old_ctx;
 
-       old_ctx = read_c0_entryhi() & ASID_MASK;
+       old_ctx = read_c0_entryhi() & cpu_asid_mask(&current_cpu_data);
        write_c0_entrylo0(0);
        while (entry < current_cpu_data.tlbsize) {
                write_c0_index(entry << 8);
@@ -81,6 +81,7 @@ void local_flush_tlb_mm(struct mm_struct *mm)
 void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                           unsigned long end)
 {
+       unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
        struct mm_struct *mm = vma->vm_mm;
        int cpu = smp_processor_id();
 
@@ -89,13 +90,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 
 #ifdef DEBUG_TLB
                printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
-                       cpu_context(cpu, mm) & ASID_MASK, start, end);
+                       cpu_context(cpu, mm) & asid_mask, start, end);
 #endif
                local_irq_save(flags);
                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
                if (size <= current_cpu_data.tlbsize) {
-                       int oldpid = read_c0_entryhi() & ASID_MASK;
-                       int newpid = cpu_context(cpu, mm) & ASID_MASK;
+                       int oldpid = read_c0_entryhi() & asid_mask;
+                       int newpid = cpu_context(cpu, mm) & asid_mask;
 
                        start &= PAGE_MASK;
                        end += PAGE_SIZE - 1;
@@ -159,6 +160,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
+       unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
        int cpu = smp_processor_id();
 
        if (cpu_context(cpu, vma->vm_mm) != 0) {
@@ -168,10 +170,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 #ifdef DEBUG_TLB
                printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
 #endif
-               newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK;
+               newpid = cpu_context(cpu, vma->vm_mm) & asid_mask;
                page &= PAGE_MASK;
                local_irq_save(flags);
-               oldpid = read_c0_entryhi() & ASID_MASK;
+               oldpid = read_c0_entryhi() & asid_mask;
                write_c0_entryhi(page | newpid);
                BARRIER;
                tlb_probe();
@@ -190,6 +192,7 @@ finish:
 
 void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
+       unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
        unsigned long flags;
        int idx, pid;
 
@@ -199,10 +202,10 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
        if (current->active_mm != vma->vm_mm)
                return;
 
-       pid = read_c0_entryhi() & ASID_MASK;
+       pid = read_c0_entryhi() & asid_mask;
 
 #ifdef DEBUG_TLB
-       if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
+       if ((pid != (cpu_context(cpu, vma->vm_mm) & asid_mask)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
                printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
                       (cpu_context(cpu, vma->vm_mm)), pid);
        }
@@ -228,6 +231,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
                     unsigned long entryhi, unsigned long pagemask)
 {
+       unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
        unsigned long flags;
        unsigned long old_ctx;
        static unsigned long wired = 0;
@@ -243,7 +247,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 
                local_irq_save(flags);
                /* Save old context and create impossible VPN2 value */
-               old_ctx = read_c0_entryhi() & ASID_MASK;
+               old_ctx = read_c0_entryhi() & asid_mask;
                old_pagemask = read_c0_pagemask();
                w = read_c0_wired();
                write_c0_wired(w + 1);
@@ -266,7 +270,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 #endif
 
                local_irq_save(flags);
-               old_ctx = read_c0_entryhi() & ASID_MASK;
+               old_ctx = read_c0_entryhi() & asid_mask;
                write_c0_entrylo0(entrylo0);
                write_c0_entryhi(entryhi);
                write_c0_index(wired);
index c17d7627f872bffd148dc093386a3cf8efd4ebd8..5a5c7fec645e8f328fe0b1cd5f8f810be86049ce 100644 (file)
 extern void build_tlb_refill_handler(void);
 
 /*
- * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
- * unfortunately, itlb is not totally transparent to software.
+ * LOONGSON-2 has a 4 entry itlb which is a subset of jtlb, LOONGSON-3 has
+ * a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. Unfortunately,
+ * itlb/dtlb are not totally transparent to software.
  */
-static inline void flush_itlb(void)
+static inline void flush_micro_tlb(void)
 {
        switch (current_cpu_type()) {
        case CPU_LOONGSON2:
+               write_c0_diag(LOONGSON_DIAG_ITLB);
+               break;
        case CPU_LOONGSON3:
-               write_c0_diag(4);
+               write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
                break;
        default:
                break;
        }
 }
 
-static inline void flush_itlb_vm(struct vm_area_struct *vma)
+static inline void flush_micro_tlb_vm(struct vm_area_struct *vma)
 {
        if (vma->vm_flags & VM_EXEC)
-               flush_itlb();
+               flush_micro_tlb();
 }
 
 void local_flush_tlb_all(void)
@@ -93,7 +96,7 @@ void local_flush_tlb_all(void)
        tlbw_use_hazard();
        write_c0_entryhi(old_ctx);
        htw_start();
-       flush_itlb();
+       flush_micro_tlb();
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL(local_flush_tlb_all);
@@ -159,7 +162,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                } else {
                        drop_mmu_context(mm, cpu);
                }
-               flush_itlb();
+               flush_micro_tlb();
                local_irq_restore(flags);
        }
 }
@@ -205,7 +208,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
        } else {
                local_flush_tlb_all();
        }
-       flush_itlb();
+       flush_micro_tlb();
        local_irq_restore(flags);
 }
 
@@ -240,7 +243,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
        finish:
                write_c0_entryhi(oldpid);
                htw_start();
-               flush_itlb_vm(vma);
+               flush_micro_tlb_vm(vma);
                local_irq_restore(flags);
        }
 }
@@ -274,7 +277,7 @@ void local_flush_tlb_one(unsigned long page)
        }
        write_c0_entryhi(oldpid);
        htw_start();
-       flush_itlb();
+       flush_micro_tlb();
        local_irq_restore(flags);
 }
 
@@ -301,7 +304,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        local_irq_save(flags);
 
        htw_stop();
-       pid = read_c0_entryhi() & ASID_MASK;
+       pid = read_c0_entryhi() & cpu_asid_mask(&current_cpu_data);
        address &= (PAGE_MASK << 1);
        write_c0_entryhi(address | pid);
        pgdp = pgd_offset(vma->vm_mm, address);
@@ -336,10 +339,12 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 #ifdef CONFIG_XPA
                write_c0_entrylo0(pte_to_entrylo(ptep->pte_high));
-               writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK);
+               if (cpu_has_xpa)
+                       writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK);
                ptep++;
                write_c0_entrylo1(pte_to_entrylo(ptep->pte_high));
-               writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK);
+               if (cpu_has_xpa)
+                       writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK);
 #else
                write_c0_entrylo0(ptep->pte_high);
                ptep++;
@@ -357,7 +362,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        }
        tlbw_use_hazard();
        htw_start();
-       flush_itlb_vm(vma);
+       flush_micro_tlb_vm(vma);
        local_irq_restore(flags);
 }
 
index 138a2ec7cc6b7785069f64401c39c9b569ff497e..e86e2e55ad3efb736875f954560f2549dbf3b534 100644 (file)
@@ -194,7 +194,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        if (current->active_mm != vma->vm_mm)
                return;
 
-       pid = read_c0_entryhi() & ASID_MASK;
+       pid = read_c0_entryhi() & cpu_asid_mask(&current_cpu_data);
 
        local_irq_save(flags);
        address &= PAGE_MASK;
index 84c6e3fda84af1f87f025c63709ecd48327fb75e..274da90adf0d682cb00f8811de9c19ba45fc3fa8 100644 (file)
@@ -234,20 +234,16 @@ static void output_pgtable_bits_defines(void)
        pr_debug("\n");
 
        pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT);
-       pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT);
+       pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
        pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT);
        pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT);
        pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT);
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
 #endif
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
-       if (cpu_has_rixi) {
 #ifdef _PAGE_NO_EXEC_SHIFT
+       if (cpu_has_rixi)
                pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
-               pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
-#endif
-       }
 #endif
        pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT);
        pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT);
@@ -284,7 +280,12 @@ static inline void dump_handler(const char *symbol, const u32 *handler, int coun
 #define C0_ENTRYLO1    3, 0
 #define C0_CONTEXT     4, 0
 #define C0_PAGEMASK    5, 0
+#define C0_PWBASE      5, 5
+#define C0_PWFIELD     5, 6
+#define C0_PWSIZE      5, 7
+#define C0_PWCTL       6, 6
 #define C0_BADVADDR    8, 0
+#define C0_PGD         9, 7
 #define C0_ENTRYHI     10, 0
 #define C0_EPC         14, 0
 #define C0_XCONTEXT    20, 0
@@ -630,6 +631,11 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 static __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
                                                        unsigned int reg)
 {
+       if (_PAGE_GLOBAL_SHIFT == 0) {
+               /* pte_t is already in EntryLo format */
+               return;
+       }
+
        if (cpu_has_rixi && _PAGE_NO_EXEC) {
                if (fill_includes_sw_bits) {
                        UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
@@ -808,7 +814,10 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 
        if (pgd_reg != -1) {
                /* pgd is in pgd_reg */
-               UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
+               if (cpu_has_ldpte)
+                       UASM_i_MFC0(p, ptr, C0_PWBASE);
+               else
+                       UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
        } else {
 #if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
                /*
@@ -1007,39 +1016,40 @@ static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
 
 static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
 {
-       /*
-        * 64bit address support (36bit on a 32bit CPU) in a 32bit
-        * Kernel is a special case. Only a few CPUs use it.
-        */
-       if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) {
-               int pte_off_even = sizeof(pte_t) / 2;
-               int pte_off_odd = pte_off_even + sizeof(pte_t);
-#ifdef CONFIG_XPA
-               const int scratch = 1; /* Our extra working register */
+       int pte_off_even = 0;
+       int pte_off_odd = sizeof(pte_t);
 
-               uasm_i_addu(p, scratch, 0, ptep);
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_PHYS_ADDR_T_64BIT)
+       /* The low 32 bits of EntryLo is stored in pte_high */
+       pte_off_even += offsetof(pte_t, pte_high);
+       pte_off_odd += offsetof(pte_t, pte_high);
 #endif
+
+       if (config_enabled(CONFIG_XPA)) {
                uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */
-               uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */
                UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
-               UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
                UASM_i_MTC0(p, tmp, C0_ENTRYLO0);
-               UASM_i_MTC0(p, ptep, C0_ENTRYLO1);
-#ifdef CONFIG_XPA
-               uasm_i_lw(p, tmp, 0, scratch);
-               uasm_i_lw(p, ptep, sizeof(pte_t), scratch);
-               uasm_i_lui(p, scratch, 0xff);
-               uasm_i_ori(p, scratch, scratch, 0xffff);
-               uasm_i_and(p, tmp, scratch, tmp);
-               uasm_i_and(p, ptep, scratch, ptep);
-               uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
-               uasm_i_mthc0(p, ptep, C0_ENTRYLO1);
-#endif
+
+               if (cpu_has_xpa && !mips_xpa_disabled) {
+                       uasm_i_lw(p, tmp, 0, ptep);
+                       uasm_i_ext(p, tmp, tmp, 0, 24);
+                       uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
+               }
+
+               uasm_i_lw(p, tmp, pte_off_odd, ptep); /* odd pte */
+               UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
+               UASM_i_MTC0(p, tmp, C0_ENTRYLO1);
+
+               if (cpu_has_xpa && !mips_xpa_disabled) {
+                       uasm_i_lw(p, tmp, sizeof(pte_t), ptep);
+                       uasm_i_ext(p, tmp, tmp, 0, 24);
+                       uasm_i_mthc0(p, tmp, C0_ENTRYLO1);
+               }
                return;
        }
 
-       UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
-       UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
+       UASM_i_LW(p, tmp, pte_off_even, ptep); /* get even pte */
+       UASM_i_LW(p, ptep, pte_off_odd, ptep); /* get odd pte */
        if (r45k_bvahwbug())
                build_tlb_probe_entry(p);
        build_convert_pte_to_entrylo(p, tmp);
@@ -1421,6 +1431,108 @@ static void build_r4000_tlb_refill_handler(void)
        dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
 }
 
+static void setup_pw(void)
+{
+       unsigned long pgd_i, pgd_w;
+#ifndef __PAGETABLE_PMD_FOLDED
+       unsigned long pmd_i, pmd_w;
+#endif
+       unsigned long pt_i, pt_w;
+       unsigned long pte_i, pte_w;
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+       unsigned long psn;
+
+       psn = ilog2(_PAGE_HUGE);     /* bit used to indicate huge page */
+#endif
+       pgd_i = PGDIR_SHIFT;  /* 1st level PGD */
+#ifndef __PAGETABLE_PMD_FOLDED
+       pgd_w = PGDIR_SHIFT - PMD_SHIFT + PGD_ORDER;
+
+       pmd_i = PMD_SHIFT;    /* 2nd level PMD */
+       pmd_w = PMD_SHIFT - PAGE_SHIFT;
+#else
+       pgd_w = PGDIR_SHIFT - PAGE_SHIFT + PGD_ORDER;
+#endif
+
+       pt_i  = PAGE_SHIFT;    /* 3rd level PTE */
+       pt_w  = PAGE_SHIFT - 3;
+
+       pte_i = ilog2(_PAGE_GLOBAL);
+       pte_w = 0;
+
+#ifndef __PAGETABLE_PMD_FOLDED
+       write_c0_pwfield(pgd_i << 24 | pmd_i << 12 | pt_i << 6 | pte_i);
+       write_c0_pwsize(1 << 30 | pgd_w << 24 | pmd_w << 12 | pt_w << 6 | pte_w);
+#else
+       write_c0_pwfield(pgd_i << 24 | pt_i << 6 | pte_i);
+       write_c0_pwsize(1 << 30 | pgd_w << 24 | pt_w << 6 | pte_w);
+#endif
+
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+       write_c0_pwctl(1 << 6 | psn);
+#endif
+       write_c0_kpgd(swapper_pg_dir);
+       kscratch_used_mask |= (1 << 7); /* KScratch6 is used for KPGD */
+}
+
+static void build_loongson3_tlb_refill_handler(void)
+{
+       u32 *p = tlb_handler;
+       struct uasm_label *l = labels;
+       struct uasm_reloc *r = relocs;
+
+       memset(labels, 0, sizeof(labels));
+       memset(relocs, 0, sizeof(relocs));
+       memset(tlb_handler, 0, sizeof(tlb_handler));
+
+       if (check_for_high_segbits) {
+               uasm_i_dmfc0(&p, K0, C0_BADVADDR);
+               uasm_i_dsrl_safe(&p, K1, K0, PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
+               uasm_il_beqz(&p, &r, K1, label_vmalloc);
+               uasm_i_nop(&p);
+
+               uasm_il_bgez(&p, &r, K0, label_large_segbits_fault);
+               uasm_i_nop(&p);
+               uasm_l_vmalloc(&l, p);
+       }
+
+       uasm_i_dmfc0(&p, K1, C0_PGD);
+
+       uasm_i_lddir(&p, K0, K1, 3);  /* global page dir */
+#ifndef __PAGETABLE_PMD_FOLDED
+       uasm_i_lddir(&p, K1, K0, 1);  /* middle page dir */
+#endif
+       uasm_i_ldpte(&p, K1, 0);      /* even */
+       uasm_i_ldpte(&p, K1, 1);      /* odd */
+       uasm_i_tlbwr(&p);
+
+       /* restore page mask */
+       if (PM_DEFAULT_MASK >> 16) {
+               uasm_i_lui(&p, K0, PM_DEFAULT_MASK >> 16);
+               uasm_i_ori(&p, K0, K0, PM_DEFAULT_MASK & 0xffff);
+               uasm_i_mtc0(&p, K0, C0_PAGEMASK);
+       } else if (PM_DEFAULT_MASK) {
+               uasm_i_ori(&p, K0, 0, PM_DEFAULT_MASK);
+               uasm_i_mtc0(&p, K0, C0_PAGEMASK);
+       } else {
+               uasm_i_mtc0(&p, 0, C0_PAGEMASK);
+       }
+
+       uasm_i_eret(&p);
+
+       if (check_for_high_segbits) {
+               uasm_l_large_segbits_fault(&l, p);
+               UASM_i_LA(&p, K1, (unsigned long)tlb_do_page_fault_0);
+               uasm_i_jr(&p, K1);
+               uasm_i_nop(&p);
+       }
+
+       uasm_resolve_relocs(relocs, labels);
+       memcpy((void *)(ebase + 0x80), tlb_handler, 0x80);
+       local_flush_icache_range(ebase + 0x80, ebase + 0x100);
+       dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32);
+}
+
 extern u32 handle_tlbl[], handle_tlbl_end[];
 extern u32 handle_tlbs[], handle_tlbs_end[];
 extern u32 handle_tlbm[], handle_tlbm_end[];
@@ -1468,7 +1580,10 @@ static void build_setup_pgd(void)
        } else {
                /* PGD in c0_KScratch */
                uasm_i_jr(&p, 31);
-               UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+               if (cpu_has_ldpte)
+                       UASM_i_MTC0(&p, a0, C0_PWBASE);
+               else
+                       UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
        }
 #else
 #ifdef CONFIG_SMP
@@ -1523,19 +1638,19 @@ iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
 
 static void
 iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
-       unsigned int mode)
+       unsigned int mode, unsigned int scratch)
 {
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
        unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY);
+       unsigned int swmode = mode & ~hwmode;
 
-       if (!cpu_has_64bits) {
-               const int scratch = 1; /* Our extra working register */
-
-               uasm_i_lui(p, scratch, (mode >> 16));
+       if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) {
+               uasm_i_lui(p, scratch, swmode >> 16);
                uasm_i_or(p, pte, pte, scratch);
-       } else
-#endif
-       uasm_i_ori(p, pte, pte, mode);
+               BUG_ON(swmode & 0xffff);
+       } else {
+               uasm_i_ori(p, pte, pte, mode);
+       }
+
 #ifdef CONFIG_SMP
 # ifdef CONFIG_PHYS_ADDR_T_64BIT
        if (cpu_has_64bits)
@@ -1554,6 +1669,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
                /* no uasm_i_nop needed */
                uasm_i_ll(p, pte, sizeof(pte_t) / 2, ptr);
                uasm_i_ori(p, pte, pte, hwmode);
+               BUG_ON(hwmode & ~0xffff);
                uasm_i_sc(p, pte, sizeof(pte_t) / 2, ptr);
                uasm_il_beqz(p, r, pte, label_smp_pgtable_change);
                /* no uasm_i_nop needed */
@@ -1575,6 +1691,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
        if (!cpu_has_64bits) {
                uasm_i_lw(p, pte, sizeof(pte_t) / 2, ptr);
                uasm_i_ori(p, pte, pte, hwmode);
+               BUG_ON(hwmode & ~0xffff);
                uasm_i_sw(p, pte, sizeof(pte_t) / 2, ptr);
                uasm_i_lw(p, pte, 0, ptr);
        }
@@ -1615,9 +1732,8 @@ build_pte_present(u32 **p, struct uasm_reloc **r,
                        cur = t;
                }
                uasm_i_andi(p, t, cur,
-                       (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT);
-               uasm_i_xori(p, t, t,
-                       (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT);
+                       (_PAGE_PRESENT | _PAGE_NO_READ) >> _PAGE_PRESENT_SHIFT);
+               uasm_i_xori(p, t, t, _PAGE_PRESENT >> _PAGE_PRESENT_SHIFT);
                uasm_il_bnez(p, r, t, lid);
                if (pte == t)
                        /* You lose the SMP race :-(*/
@@ -1628,11 +1744,11 @@ build_pte_present(u32 **p, struct uasm_reloc **r,
 /* Make PTE valid, store result in PTR. */
 static void
 build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte,
-                unsigned int ptr)
+                unsigned int ptr, unsigned int scratch)
 {
        unsigned int mode = _PAGE_VALID | _PAGE_ACCESSED;
 
-       iPTE_SW(p, r, pte, ptr, mode);
+       iPTE_SW(p, r, pte, ptr, mode, scratch);
 }
 
 /*
@@ -1668,12 +1784,12 @@ build_pte_writable(u32 **p, struct uasm_reloc **r,
  */
 static void
 build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte,
-                unsigned int ptr)
+                unsigned int ptr, unsigned int scratch)
 {
        unsigned int mode = (_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID
                             | _PAGE_DIRTY);
 
-       iPTE_SW(p, r, pte, ptr, mode);
+       iPTE_SW(p, r, pte, ptr, mode, scratch);
 }
 
 /*
@@ -1778,7 +1894,7 @@ static void build_r3000_tlb_load_handler(void)
        build_r3000_tlbchange_handler_head(&p, K0, K1);
        build_pte_present(&p, &r, K0, K1, -1, label_nopage_tlbl);
        uasm_i_nop(&p); /* load delay */
-       build_make_valid(&p, &r, K0, K1);
+       build_make_valid(&p, &r, K0, K1, -1);
        build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
        uasm_l_nopage_tlbl(&l, p);
@@ -1809,7 +1925,7 @@ static void build_r3000_tlb_store_handler(void)
        build_r3000_tlbchange_handler_head(&p, K0, K1);
        build_pte_writable(&p, &r, K0, K1, -1, label_nopage_tlbs);
        uasm_i_nop(&p); /* load delay */
-       build_make_write(&p, &r, K0, K1);
+       build_make_write(&p, &r, K0, K1, -1);
        build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
        uasm_l_nopage_tlbs(&l, p);
@@ -1840,7 +1956,7 @@ static void build_r3000_tlb_modify_handler(void)
        build_r3000_tlbchange_handler_head(&p, K0, K1);
        build_pte_modifiable(&p, &r, K0, K1,  -1, label_nopage_tlbm);
        uasm_i_nop(&p); /* load delay */
-       build_make_write(&p, &r, K0, K1);
+       build_make_write(&p, &r, K0, K1, -1);
        build_r3000_pte_reload_tlbwi(&p, K0, K1);
 
        uasm_l_nopage_tlbm(&l, p);
@@ -2008,7 +2124,7 @@ static void build_r4000_tlb_load_handler(void)
                }
                uasm_l_tlbl_goaround1(&l, p);
        }
-       build_make_valid(&p, &r, wr.r1, wr.r2);
+       build_make_valid(&p, &r, wr.r1, wr.r2, wr.r3);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
@@ -2122,7 +2238,7 @@ static void build_r4000_tlb_store_handler(void)
        build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
        if (m4kc_tlbp_war())
                build_tlb_probe_entry(&p);
-       build_make_write(&p, &r, wr.r1, wr.r2);
+       build_make_write(&p, &r, wr.r1, wr.r2, wr.r3);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
@@ -2178,7 +2294,7 @@ static void build_r4000_tlb_modify_handler(void)
        if (m4kc_tlbp_war())
                build_tlb_probe_entry(&p);
        /* Present and writable bits set, set accessed and dirty bits. */
-       build_make_write(&p, &r, wr.r1, wr.r2);
+       build_make_write(&p, &r, wr.r1, wr.r2, wr.r3);
        build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
@@ -2311,9 +2427,7 @@ static void config_htw_params(void)
        if (CONFIG_PGTABLE_LEVELS >= 3)
                pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT;
 
-       /* If XPA has been enabled, PTEs are 64-bit in size. */
-       if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA))
-               pwsize |= 1;
+       pwsize |= ilog2(sizeof(pte_t)/4) << MIPS_PWSIZE_PTEW_SHIFT;
 
        write_c0_pwsize(pwsize);
 
@@ -2394,6 +2508,9 @@ void build_tlb_refill_handler(void)
         */
        static int run_once = 0;
 
+       if (config_enabled(CONFIG_XPA) && !cpu_has_rixi)
+               panic("Kernels supporting XPA currently require CPUs with RIXI");
+
        output_pgtable_bits_defines();
        check_pabits();
 
@@ -2437,13 +2554,18 @@ void build_tlb_refill_handler(void)
                break;
 
        default:
+               if (cpu_has_ldpte)
+                       setup_pw();
+
                if (!run_once) {
                        scratch_reg = allocate_kscratch();
                        build_setup_pgd();
                        build_r4000_tlb_load_handler();
                        build_r4000_tlb_store_handler();
                        build_r4000_tlb_modify_handler();
-                       if (!cpu_has_local_ebase)
+                       if (cpu_has_ldpte)
+                               build_loongson3_tlb_refill_handler();
+                       else if (!cpu_has_local_ebase)
                                build_r4000_tlb_refill_handler();
                        flush_tlb_handlers();
                        run_once++;
index b4a8378935625b2e1d0f228f6961ebd8208544f1..9c2220a45189a6e954a597c05bb880f700b93801 100644 (file)
@@ -153,6 +153,8 @@ static struct insn insn_table[] = {
        { 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_ldpte, M(lwc2_op, 0, 0, 0, ldpte_op, mult_op), RS | RD },
+       { insn_lddir, M(lwc2_op, 0, 0, 0, lddir_op, mult_op), RS | RT | RD },
        { insn_invalid, 0, 0 }
 };
 
index 319051c34343ae9e0eb7c5d4adf82732e5598cd6..ad718debc35a74d62c2d0b532420b2711a5c4416 100644 (file)
@@ -60,6 +60,7 @@ enum opcode {
        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,
+       insn_lddir, insn_ldpte,
 };
 
 struct insn {
@@ -335,6 +336,8 @@ I_u1u2s3(_bbit0);
 I_u1u2s3(_bbit1);
 I_u3u1u2(_lwx)
 I_u3u1u2(_ldx)
+I_u1u2(_ldpte)
+I_u2u1u3(_lddir)
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 #include <asm/octeon/octeon.h>
index 4740c82fb97a14e95118d05590b66b3192e9f1f5..33d5ff5069e53b72f1bc5e2225d7e63759e945e8 100644 (file)
@@ -248,10 +248,15 @@ static void __init bonito_quirks_setup(void)
 #endif
 }
 
+void __init *plat_get_fdt(void)
+{
+       return (void *)__dtb_start;
+}
+
 void __init plat_mem_setup(void)
 {
        unsigned int i;
-       void *fdt = __dtb_start;
+       void *fdt = plat_get_fdt();
 
        fdt = malta_dt_shim(fdt);
        __dt_setup_arch(fdt);
index b7bf721eabf5411bfb2f55b6b7d2cdc9ba887f96..7407da04f8d6bc1cf0da21b4800530087f7d0c88 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/i8253.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
+#include <linux/math64.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
@@ -72,6 +73,8 @@ static void __init estimate_frequencies(void)
 {
        unsigned long flags;
        unsigned int count, start;
+       unsigned char secs1, secs2, ctrl;
+       int secs;
        cycle_t giccount = 0, gicstart = 0;
 
 #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ
@@ -81,32 +84,51 @@ static void __init estimate_frequencies(void)
 
        local_irq_save(flags);
 
-       /* Start counter exactly on falling edge of update flag. */
+       if (gic_present)
+               gic_start_count();
+
+       /*
+        * Read counters exactly on rising edge of update flag.
+        * This helps get an accurate reading under virtualisation.
+        */
        while (CMOS_READ(RTC_REG_A) & RTC_UIP);
        while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
-
-       /* Initialize counters. */
        start = read_c0_count();
-       if (gic_present) {
-               gic_start_count();
+       if (gic_present)
                gicstart = gic_read_count();
-       }
 
-       /* Read counter exactly on falling edge of update flag. */
+       /* Wait for falling edge before reading RTC. */
        while (CMOS_READ(RTC_REG_A) & RTC_UIP);
-       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+       secs1 = CMOS_READ(RTC_SECONDS);
 
+       /* Read counters again exactly on rising edge of update flag. */
+       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
        count = read_c0_count();
        if (gic_present)
                giccount = gic_read_count();
 
+       /* Wait for falling edge before reading RTC again. */
+       while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+       secs2 = CMOS_READ(RTC_SECONDS);
+
+       ctrl = CMOS_READ(RTC_CONTROL);
+
        local_irq_restore(flags);
 
+       if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+               secs1 = bcd2bin(secs1);
+               secs2 = bcd2bin(secs2);
+       }
+       secs = secs2 - secs1;
+       if (secs < 1)
+               secs += 60;
+
        count -= start;
+       count /= secs;
        mips_hpt_frequency = count;
 
        if (gic_present) {
-               giccount -= gicstart;
+               giccount = div_u64(giccount - gicstart, secs);
                gic_frequency = giccount;
        }
 }
index e43f4801a2455d175cc43695e8020138449a5195..9f2f9b2b23cedd5464b3a491128ef8b36424ea48 100644 (file)
@@ -83,6 +83,11 @@ static void __init parse_memsize_param(void)
        }
 }
 
+void __init *plat_get_fdt(void)
+{
+       return (void *)__dtb_start;
+}
+
 void __init plat_mem_setup(void)
 {
        /* allow command line/bootloader env to override memory size in DT */
index edbab9b8691fe377a01c9d2ba64aa7a69923b1a6..c474981a6c0dd473627ac14ecd40430ded4d0f71 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/netlogic/xlp-hal/sys.h>
 #include <asm/netlogic/xlp-hal/cpucontrol.h>
 
-#define CP0_EBASE      $15
 #define SYS_CPU_COHERENT_BASE  CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
                        XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \
                        SYS_CPU_NONCOHERENT_MODE * 4
@@ -92,7 +91,7 @@
  * registers. On XLPII CPUs, usual cache instructions work.
  */
 .macro xlp_flush_l1_dcache
-       mfc0    t0, CP0_EBASE, 0
+       mfc0    t0, CP0_PRID
        andi    t0, t0, PRID_IMP_MASK
        slt     t1, t0, 0x1200
        beqz    t1, 15f
@@ -171,7 +170,7 @@ FEXPORT(nlm_reset_entry)
        nop
 
 1:     /* Entry point on core wakeup */
-       mfc0    t0, CP0_EBASE, 0        /* processor ID */
+       mfc0    t0, CP0_PRID            /* processor ID */
        andi    t0, PRID_IMP_MASK
        li      t1, 0x1500              /* XLP 9xx */
        beq     t0, t1, 2f              /* does not need to set coherent */
@@ -182,8 +181,8 @@ FEXPORT(nlm_reset_entry)
        nop
 
        /* set bit in SYS coherent register for the core */
-       mfc0    t0, CP0_EBASE, 1
-       mfc0    t1, CP0_EBASE, 1
+       mfc0    t0, CP0_EBASE
+       mfc0    t1, CP0_EBASE
        srl     t1, 5
        andi    t1, 0x3                 /* t1 <- node */
        li      t2, 0x40000
@@ -232,7 +231,7 @@ EXPORT(nlm_boot_siblings)
 
         * NOTE: All GPR contents are lost after the mtcr above!
         */
-       mfc0    v0, CP0_EBASE, 1
+       mfc0    v0, CP0_EBASE
        andi    v0, 0x3ff               /* v0 <- node/core */
 
        /*
index 805355b0bd05d4b6d7de3493c2cbf446c737235d..f0cc4c9de2bbcdc655b861f189f16bebb9ea7d8b 100644 (file)
@@ -48,8 +48,6 @@
 #include <asm/netlogic/xlp-hal/sys.h>
 #include <asm/netlogic/xlp-hal/cpucontrol.h>
 
-#define CP0_EBASE      $15
-
        .set    noreorder
        .set    noat
        .set    arch=xlr                /* for mfcr/mtcr, XLR is sufficient */
@@ -86,7 +84,7 @@ NESTED(nlm_boot_secondary_cpus, 16, sp)
        PTR_L   gp, 0(t1)
 
        /* a0 has the processor id */
-       mfc0    a0, CP0_EBASE, 1
+       mfc0    a0, CP0_EBASE
        andi    a0, 0x3ff               /* a0 <- node/core */
        PTR_LA  t0, nlm_early_init_secondary
        jalr    t0
index 80ec929747c37b30eb8da5749c21134b1c0b4558..25ee69489e5eb8615a5c5a6fdcf199a1e8fb33d8 100644 (file)
@@ -58,7 +58,7 @@ void nlm_node_init(int node)
                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));
+       nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
        if (cpu_is_xlp9xx())
                nodep->socbus = xlp9xx_get_socbus(node);
        else
index d118b9aa7647408035c64935b7b222d60b6c0cc8..72ceddc9a03ff8afb00496e6187a3fa3e17a8c6c 100644 (file)
@@ -168,7 +168,7 @@ static void nlm_init_node(void)
 
        nodep = nlm_current_node();
        nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
-       nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+       nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
        spin_lock_init(&nodep->piclock);
 }
 
index 3c9ec3ddca845dccac627dcf13fec4a7b62ee272..2f33992f6dff00dbf54321a5f00089e73acd14e5 100644 (file)
@@ -77,7 +77,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        struct op_mips_model *lmodel = NULL;
        int res;
 
-       switch (current_cpu_type()) {
+       switch (boot_cpu_type()) {
        case CPU_5KC:
        case CPU_M14KC:
        case CPU_M14KEC:
index 8f988a61b7a850526e623733a969b405f7755fce..45cb27469fbaa14db9824f9635287b0507498354 100644 (file)
@@ -269,11 +269,9 @@ static int mipsxx_perfcount_handler(void)
        return handled;
 }
 
-#define M_CONFIG1_PC   (1 << 4)
-
 static inline int __n_counters(void)
 {
-       if (!(read_c0_config1() & M_CONFIG1_PC))
+       if (!cpu_has_perf)
                return 0;
        if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
                return 1;
index c2ce41ea61d724d4872c2fd940f70af75e48d16e..2b5427d3f35c255bc566978b02ff1ac8e057f551 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/of_irq.h>
index e5738ee26f4f1e21303d932f58f0b2d1bb4dd741..f51e10899cc28b566cf26d986555fbd6c407bec9 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/types.h>
index 28952637a862b3a94fd45040f4a692c322c1730b..c8994c156e2ddad2c0bde912c553f66015c8d757 100644 (file)
@@ -76,7 +76,7 @@ static void mod_wired_entry(int entry, unsigned long entrylo0,
        unsigned long old_ctx;
 
        /* Save old context and create impossible VPN2 value */
-       old_ctx = read_c0_entryhi() & 0xff;
+       old_ctx = read_c0_entryhi() & MIPS_ENTRYHI_ASID;
        old_pagemask = read_c0_pagemask();
        write_c0_index(entry);
        write_c0_pagemask(pagemask);
index b1e061f7fdc7115a08b168afd49e0e4af9816a72..7ae89d0c70990b31a039f9caa8c2c987c2e9845b 100644 (file)
@@ -116,7 +116,6 @@ static struct pci_controller mace_pci_controller = {
        .pci_ops        = &mace_pci_ops,
        .mem_resource   = &mace_pci_mem_resource,
        .io_resource    = &mace_pci_io_resource,
-       .iommu          = 0,
        .mem_offset     = MACE_PCI_MEM_OFFSET,
        .io_offset      = 0,
        .io_map_base    = CKSEG1ADDR(MACEPCI_LOW_IO),
index 6a15dbd085aa8e600a59d5a0680cd9be1a3f3f60..b9deab17ccf246130760565cc1b387fdea5997ca 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/types.h>
index 66bf6cd6be3c3220cd0a1b00bfcf92e8e374e30d..0cc71253a4978dcf81c89542e85b611745901852 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_PCI_H__
index 1ae932c2d78b364b6c93b142d075c6a42bb1c7b6..6ce81620169956564ab96a0cda2b22e3cf756e27 100644 (file)
@@ -2,7 +2,7 @@
  *  Ralink MT7620A SoC PCI support
  *
  *  Copyright (C) 2007-2013 Bruce Chang (Mediatek)
- *  Copyright (C) 2013-2016 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2016 John Crispin <john@phrozen.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
index a245cad4372a4a84094b88eed05ba3080a146190..f2a1050168d9592c0a0940b9f996f4c1141285cc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Ralink RT288x SoC PCI register definitions
  *
- *  Copyright (C) 2009 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2009 John Crispin <john@phrozen.org>
  *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
  *
  *  Parts of this file are based on Ralink's 2.6.21 BSP
index b8a0bf5766f2efb64380ae3dedddca3b4782da03..f1b11f0dea2d8e71e8f5b6cbf65ad4d9e54d0501 100644 (file)
@@ -83,9 +83,6 @@ static void pcibios_scanbus(struct pci_controller *hose)
        LIST_HEAD(resources);
        struct pci_bus *bus;
 
-       if (!hose->iommu)
-               PCI_DMA_BUS_IS_PHYS = 1;
-
        if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY))
                next_busno = (*hose->get_busno)();
 
index ca6a62bb10dbe0c71fb28d5ed9fe08b7dbc3bf17..62a0a78b6c6446c58cb2ac08bf61157e40c4c6ed 100644 (file)
  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  *  for more details.
  */
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/init.h>
+#include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
-#include <linux/irqdomain.h>
 
 #include <asm/time.h>
 
@@ -58,16 +57,12 @@ unsigned int get_c0_compare_int(void)
 
 void __init plat_time_init(void)
 {
-       struct clk *clk;
+       unsigned long rate = pic32_get_pbclk(7);
 
        of_clk_init(NULL);
-       clk = clk_get_sys("cpu_clk", NULL);
-       if (IS_ERR(clk))
-               panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
 
-       clk_prepare_enable(clk);
-       pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
-       mips_hpt_frequency = clk_get_rate(clk) / 2;
+       pr_info("CPU Clock: %ldMHz\n", rate / 1000000);
+       mips_hpt_frequency = rate / 2;
 
        clocksource_probe();
 }
index 96ba2cc9ad3e34da3948c3103d41629e24c88227..956c92eabfaba73cad83ab35539fd8b166ca502e 100644 (file)
@@ -2,6 +2,7 @@
  * Pistachio platform setup
  *
  * Copyright (C) 2014 Google, Inc.
+ * Copyright (C) 2016 Imagination Technologies
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -9,6 +10,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <asm/smp-ops.h>
 #include <asm/traps.h>
 
+/*
+ * Core revision register decoding
+ * Bits 23 to 20: Major rev
+ * Bits 15 to 8: Minor rev
+ * Bits 7 to 0: Maintenance rev
+ */
+#define PISTACHIO_CORE_REV_REG 0xB81483D0
+#define PISTACHIO_CORE_REV_A1  0x00100006
+#define PISTACHIO_CORE_REV_B0  0x00100106
+
 const char *get_system_type(void)
 {
-       return "IMG Pistachio SoC";
+       u32 core_rev;
+       const char *sys_type;
+
+       core_rev = __raw_readl((const void *)PISTACHIO_CORE_REV_REG);
+
+       switch (core_rev) {
+       case PISTACHIO_CORE_REV_B0:
+               sys_type = "IMG Pistachio SoC (B0)";
+               break;
+
+       case PISTACHIO_CORE_REV_A1:
+               sys_type = "IMG Pistachio SoC (A1)";
+               break;
+
+       default:
+               sys_type = "IMG Pistachio SoC";
+               break;
+       }
+
+       return sys_type;
 }
 
 static void __init plat_setup_iocoherency(void)
@@ -109,6 +140,8 @@ void __init prom_init(void)
        mips_cm_probe();
        mips_cpc_probe();
        register_cps_smp_ops();
+
+       pr_info("SoC Type: %s\n", get_system_type());
 }
 
 void __init prom_free_prom_memory(void)
index 9d293b3e9130152af49f964e530ece27e482fd7b..a63b73610fd490d1c58293885b474e929f5bd1be 100644 (file)
@@ -118,7 +118,7 @@ void msp_restart(char *command)
        /* No chip-specific reset code, just jump to the ROM reset vector */
        set_c0_status(ST0_BEV | ST0_ERL);
        change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-       flush_cache_all();
+       __flush_cache_all();
        write_c0_wired(0);
 
        __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
index 99b4d94236cc50d56726a35949e11a24573ce561..8a7443b2535ebcd4f16c801ee1865fcc56047b05 100644 (file)
@@ -38,9 +38,6 @@ extern void pnx833x_machine_power_off(void);
 
 int __init plat_mem_setup(void)
 {
-       /* fake pci bus to avoid bounce buffers */
-       PCI_DMA_BUS_IS_PHYS = 1;
-
        /* set mips clock to 320MHz */
 #if defined(CONFIG_SOC_PNX8335)
        PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ);
index 0d1795a0321e373d93adbfc073be4ac67423d97b..fe34715338205b08919cba055b97b950fbe83d73 100644 (file)
@@ -4,7 +4,7 @@
 # Makefile for the Ralink common stuff
 #
 # Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
-# Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+# Copyright (C) 2013 John Crispin <john@phrozen.org>
 
 obj-y := prom.o of.o reset.o
 
index 5403468394fbafcbb6a72adf2872ca9d1f31cac0..e1fa5972a81db6158e54897e218e6949ece07ae8 100644 (file)
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/debugfs.h>
index e46f91f971c54f85759067c26b8a5d27d98f6a74..3ad0b0794f7d09d5953bc26d59a27c717792ea6b 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2013 by John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 by John Crispin <john@phrozen.org>
  */
 
 #include <linux/clockchips.h>
index 25c4a61779f1f3a015b9eb7d76bdfc63e3a7dab4..ebaa7cc0e9957b63905f04f5444f81d28f043aa4 100644 (file)
@@ -4,7 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
index 8e7d8e618fb941cf490d39e56b5bdd0477f69278..b8245d0940d642ae53d729c3ec0e20c79ed4016e 100644 (file)
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RALINK_COMMON_H__
index e10d10b9e82a98bf5e53382d88cbc98b769ef53c..765d5ba98fa2440c7aec51041176f441ac1f0a29 100644 (file)
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/interrupt.h>
index 50d6c55ab1de015c20cd2c319ad4b7dde31ea7bb..2058280450b5e5d5cd867edbe1065b3be407fb60 100644 (file)
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
index 4cf77f358395d4bd92d6527ab41578fefa3691d6..4911c1445f1a44549ebfef7beb41a2006c085a85 100644 (file)
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/io.h>
index 0d3d1a97895f167d613cd469422dc4e2bfe6087c..88b82fe21ae6a9370ab36cfed3d6e350671dfcce 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
@@ -581,11 +581,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
                (rev & CHIP_REV_ECO_MASK));
 
        cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
-       if (is_mt76x8())
+       if (is_mt76x8()) {
                dram_type = cfg0 & DRAM_TYPE_MT7628_MASK;
-       else
+       } else {
                dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) &
                            SYSCFG0_DRAM_TYPE_MASK;
+               if (dram_type == SYSCFG0_DRAM_TYPE_UNKNOWN)
+                       dram_type = SYSCFG0_DRAM_TYPE_SDRAM;
+       }
 
        soc_info->mem_base = MT7620_DRAM_BASE;
        if (is_mt76x8())
index e9b9fa3e1e51b3809847e5b3f50db4515fa78666..a45bbbe97ac5f69ccd64d8a4a1939dcfc923195a 100644 (file)
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
index f9eda5d8f82cd54681efbdf65c4f55123a3dfeed..0aa67a2d0ae6e015f4111793f73b66f6fecce936 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/io.h>
index 39a9142f71be214ed97194edc15f0398a028ffbd..5a73c5e142211d484cc0589cc3ca7f9030953301 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2010 Joonas Lahtinen <joonas.lahtinen@gmail.com>
- *  Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/string.h>
index ee117c4bc4a36cc6f974c5efc89751300a535108..64543d66e76b50ccace33bf942e0b3c61c7e7fa4 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/pm.h>
@@ -61,7 +61,7 @@ static int ralink_reset_device(struct reset_controller_dev *rcdev,
        return ralink_deassert_device(rcdev, id);
 }
 
-static struct reset_control_ops reset_ops = {
+static const struct reset_control_ops reset_ops = {
        .reset = ralink_reset_device,
        .assert = ralink_assert_device,
        .deassert = ralink_deassert_device,
index 3c84166ebcb779b1f50f9711c820977295873377..285796e6d75c2207f3fa45bb48d09622afaada6c 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
index d7c4ba43a4284525b6de3b3f95daa42d8a846ad2..c8a28c4bf29edc9640bddfba59533b14e904bc11 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
index fafec947b27df7dc436d4701f698c734904e7421..4cef9162bd9b8164ca7fab6c4a2f37a5fc48ebee 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
index 5b4f186bcf958cc850083a40b77ffd07f73320bb..069771dbec42a5a12a7d8411485efd9df33c7101 100644 (file)
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
index 82c72a15bf759fb5adb914081e8ba16d42d87996..b0343ff336c5fe6dd173af86cfb341129144a725 100644 (file)
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
 */
 
 #include <linux/module.h>
@@ -180,5 +180,5 @@ static struct platform_driver rt_timer_driver = {
 module_platform_driver(rt_timer_driver);
 
 MODULE_DESCRIPTION("Ralink RT2880 timer");
-MODULE_AUTHOR("John Crispin <blogic@openwrt.org");
+MODULE_AUTHOR("John Crispin <john@phrozen.org");
 MODULE_LICENSE("GPL");
index cb9a095f5c5ec082188d21b96619c4fcb5fda7a0..707b8844156797a888ed5e152b5c3dd56c2972f5 100644 (file)
@@ -143,7 +143,8 @@ config SIBYTE_CFE_CONSOLE
 config SIBYTE_BUS_WATCHER
        bool "Support for Bus Watcher statistics"
        depends on SIBYTE_SB1xxx_SOC && \
-               (SIBYTE_BCM112X || SIBYTE_SB1250)
+               (SIBYTE_BCM112X || SIBYTE_SB1250 || \
+                SIBYTE_BCM1x55 || SIBYTE_BCM1x80)
        help
          Handle and keep statistics on the bus error interrupts (COR_ECC,
          BAD_ECC, IO_BUS).
index ee3617c0c5e2eb9388d01c1ae6e92846f86bc2a1..b369509e9753783b933280c97d32f7deba9c15a7 100644 (file)
@@ -50,13 +50,17 @@ quiet_cmd_vdsold = VDSO    $@
       cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
                    -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
 
+# Strip rule for the raw .so files
+$(obj)/%.so.raw: OBJCOPYFLAGS := -S
+$(obj)/%.so.raw: $(obj)/%.so.dbg.raw FORCE
+       $(call if_changed,objcopy)
+
 hostprogs-y := genvdso
 
 quiet_cmd_genvdso = GENVDSO $@
 define cmd_genvdso
-       cp $< $(<:%.dbg=%) && \
-       $(OBJCOPY) -S $< $(<:%.dbg=%) && \
-       $(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME)
+       $(foreach file,$(filter %.raw,$^),cp $(file) $(file:%.raw=%) &&) \
+       $(obj)/genvdso $(<:%.raw=%) $(<:%.dbg.raw=%) $@ $(VDSO_NAME)
 endef
 
 #
@@ -66,7 +70,10 @@ endef
 native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS))
 
 targets += $(obj-vdso-y)
-targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c
+targets += vdso.lds
+targets += vdso.so.dbg.raw vdso.so.raw
+targets += vdso.so.dbg vdso.so
+targets += vdso-image.c
 
 obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o)
 
@@ -75,10 +82,11 @@ $(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi)
 
 $(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi)
 
-$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
+$(obj)/vdso.so.dbg.raw: $(obj)/vdso.lds $(obj-vdso) FORCE
        $(call if_changed,vdsold)
 
-$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE
+$(obj)/vdso-image.c: $(obj)/vdso.so.dbg.raw $(obj)/vdso.so.raw \
+                     $(obj)/genvdso FORCE
        $(call if_changed,genvdso)
 
 obj-y += vdso-image.o
@@ -89,7 +97,10 @@ obj-y += vdso-image.o
 
 # Define these outside the ifdef to ensure they are picked up by clean.
 targets += $(obj-vdso-y:%.o=%-o32.o)
-targets += vdso-o32.lds vdso-o32.so.dbg vdso-o32.so vdso-o32-image.c
+targets += vdso-o32.lds
+targets += vdso-o32.so.dbg.raw vdso-o32.so.raw
+targets += vdso-o32.so.dbg vdso-o32.so
+targets += vdso-o32-image.c
 
 ifdef CONFIG_MIPS32_O32
 
@@ -109,11 +120,12 @@ $(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
 $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
-$(obj)/vdso-o32.so.dbg: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
+$(obj)/vdso-o32.so.dbg.raw: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
        $(call if_changed,vdsold)
 
 $(obj)/vdso-o32-image.c: VDSO_NAME := o32
-$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg $(obj)/genvdso FORCE
+$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg.raw $(obj)/vdso-o32.so.raw \
+                         $(obj)/genvdso FORCE
        $(call if_changed,genvdso)
 
 obj-y += vdso-o32-image.o
@@ -125,7 +137,10 @@ endif
 #
 
 targets += $(obj-vdso-y:%.o=%-n32.o)
-targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c
+targets += vdso-n32.lds
+targets += vdso-n32.so.dbg.raw vdso-n32.so.raw
+targets += vdso-n32.so.dbg vdso-n32.so
+targets += vdso-n32-image.c
 
 ifdef CONFIG_MIPS32_N32
 
@@ -145,11 +160,12 @@ $(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
 $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
-$(obj)/vdso-n32.so.dbg: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
+$(obj)/vdso-n32.so.dbg.raw: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
        $(call if_changed,vdsold)
 
 $(obj)/vdso-n32-image.c: VDSO_NAME := n32
-$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg $(obj)/genvdso FORCE
+$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg.raw $(obj)/vdso-n32.so.raw \
+                         $(obj)/genvdso FORCE
        $(call if_changed,genvdso)
 
 obj-y += vdso-n32-image.o
index d7f755833c3f43431b48f38b296da4df34d993e6..39a0db3e2b346f4d9164eca8935a2e4d39663026 100644 (file)
@@ -73,7 +73,7 @@ static inline void software_reset(void)
        default:
                set_c0_status(ST0_BEV | ST0_ERL);
                change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-               flush_cache_all();
+               __flush_cache_all();
                write_c0_wired(0);
                __asm__("jr     %0"::"r"(0xbfc00000));
                break;
index f364fa4d24ebffa8b9021036b3e3f22d0018da40..72fe0a5a8bf3ff2ce8cb7da6820dfdba526be3f6 100644 (file)
 #include <asm/signal.h>
 #endif
 
+#ifdef CONFIG_MIPS
+#include <asm/traps.h>
+#endif
+
 #define  ARB_ERR_CAP_CLEAR             (1 << 0)
 #define  ARB_ERR_CAP_STATUS_TIMEOUT    (1 << 12)
 #define  ARB_ERR_CAP_STATUS_TEA                (1 << 11)
@@ -238,6 +242,29 @@ static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
 }
 #endif
 
+#ifdef CONFIG_MIPS
+static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup)
+{
+       int ret = 0;
+       struct brcmstb_gisb_arb_device *gdev;
+       u32 cap_status;
+
+       list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) {
+               cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
+
+               /* Invalid captured address, bail out */
+               if (!(cap_status & ARB_ERR_CAP_STATUS_VALID)) {
+                       is_fixup = 1;
+                       goto out;
+               }
+
+               ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error");
+       }
+out:
+       return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
+}
+#endif
+
 static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
 {
        brcmstb_gisb_arb_decode_addr(dev_id, "timeout");
@@ -355,6 +382,9 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
        hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
                        "imprecise external abort");
 #endif
+#ifdef CONFIG_MIPS
+       board_be_handler = brcmstb_bus_error_handler;
+#endif
 
        dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
                        gdev->base, timeout_irq, tea_irq);
index 1c543effe062f8631c688088a1620454fadf160e..cad49bc38b3e7c7d7fd78c846fe51da7be2d1c49 100644 (file)
@@ -599,8 +599,8 @@ BUILD_PERDEV_HELPER(cpu_up)         /* int mips_cdmm_cpu_up_helper(...) */
  * mips_cdmm_bus_down() - Tear down the CDMM bus.
  * @data:      Pointer to unsigned int CPU number.
  *
- * This work_on_cpu callback function is executed on a given CPU to call the
- * CDMM driver cpu_down callback for all devices on that CPU.
+ * This function is executed on the hotplugged CPU and calls the CDMM
+ * driver cpu_down callback for all devices on that CPU.
  */
 static long mips_cdmm_bus_down(void *data)
 {
@@ -630,7 +630,9 @@ static long mips_cdmm_bus_down(void *data)
  * CDMM devices on that CPU, or to call the CDMM driver cpu_up callback for all
  * devices already discovered on that CPU.
  *
- * It is used during initialisation and when CPUs are brought online.
+ * It is used as work_on_cpu callback function during
+ * initialisation. When CPUs are brought online the function is
+ * invoked directly on the hotplugged CPU.
  */
 static long mips_cdmm_bus_up(void *data)
 {
@@ -677,10 +679,10 @@ static int mips_cdmm_cpu_notify(struct notifier_block *nb,
        switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_ONLINE:
        case CPU_DOWN_FAILED:
-               work_on_cpu(cpu, mips_cdmm_bus_up, &cpu);
+               mips_cdmm_bus_up(&cpu);
                break;
        case CPU_DOWN_PREPARE:
-               work_on_cpu(cpu, mips_cdmm_bus_down, &cpu);
+               mips_cdmm_bus_down(&cpu);
                break;
        default:
                return NOTIFY_DONE;
index c45554957499ea608a176d5515be5f21f21adf7c..90518cd7fc9c4e6447b9b22cd1f14765e75ba5cf 100644 (file)
@@ -197,6 +197,9 @@ config COMMON_CLK_PXA
        ---help---
          Support for the Marvell PXA SoC.
 
+config COMMON_CLK_PIC32
+       def_bool COMMON_CLK && MACH_PIC32
+
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
index 46869d696e4d7bba3962719fb9464684a2bb4c91..18e64bbeeaf4e3347ef5bc225648e915809fa88d 100644 (file)
@@ -58,6 +58,7 @@ obj-$(CONFIG_ARCH_MXC)                        += imx/
 obj-$(CONFIG_MACH_INGENIC)             += ingenic/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
 obj-$(CONFIG_ARCH_MEDIATEK)            += mediatek/
+obj-$(CONFIG_MACH_PIC32)               += microchip/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)                 += mmp/
 endif
diff --git a/drivers/clk/microchip/Makefile b/drivers/clk/microchip/Makefile
new file mode 100644 (file)
index 0000000..2152f41
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_COMMON_CLK_PIC32) += clk-core.o
+obj-$(CONFIG_PIC32MZDA) += clk-pic32mzda.o
diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-core.c
new file mode 100644 (file)
index 0000000..ca85cea
--- /dev/null
@@ -0,0 +1,1031 @@
+/*
+ * Purna Chandra Mandal,<purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology 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.
+ */
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <asm/mach-pic32/pic32.h>
+#include <asm/traps.h>
+
+#include "clk-core.h"
+
+/* OSCCON Reg fields */
+#define OSC_CUR_MASK           0x07
+#define OSC_CUR_SHIFT          12
+#define OSC_NEW_MASK           0x07
+#define OSC_NEW_SHIFT          8
+#define OSC_SWEN               BIT(0)
+
+/* SPLLCON Reg fields */
+#define PLL_RANGE_MASK         0x07
+#define PLL_RANGE_SHIFT                0
+#define PLL_ICLK_MASK          0x01
+#define PLL_ICLK_SHIFT         7
+#define PLL_IDIV_MASK          0x07
+#define PLL_IDIV_SHIFT         8
+#define PLL_ODIV_MASK          0x07
+#define PLL_ODIV_SHIFT         24
+#define PLL_MULT_MASK          0x7F
+#define PLL_MULT_SHIFT         16
+#define PLL_MULT_MAX           128
+#define PLL_ODIV_MIN           1
+#define PLL_ODIV_MAX           5
+
+/* Peripheral Bus Clock Reg Fields */
+#define PB_DIV_MASK            0x7f
+#define PB_DIV_SHIFT           0
+#define PB_DIV_READY           BIT(11)
+#define PB_DIV_ENABLE          BIT(15)
+#define PB_DIV_MAX             128
+#define PB_DIV_MIN             0
+
+/* Reference Oscillator Control Reg fields */
+#define REFO_SEL_MASK          0x0f
+#define REFO_SEL_SHIFT         0
+#define REFO_ACTIVE            BIT(8)
+#define REFO_DIVSW_EN          BIT(9)
+#define REFO_OE                        BIT(12)
+#define REFO_ON                        BIT(15)
+#define REFO_DIV_SHIFT         16
+#define REFO_DIV_MASK          0x7fff
+
+/* Reference Oscillator Trim Register Fields */
+#define REFO_TRIM_REG          0x10
+#define REFO_TRIM_MASK         0x1ff
+#define REFO_TRIM_SHIFT                23
+#define REFO_TRIM_MAX          511
+
+/* Mux Slew Control Register fields */
+#define SLEW_BUSY              BIT(0)
+#define SLEW_DOWNEN            BIT(1)
+#define SLEW_UPEN              BIT(2)
+#define SLEW_DIV               0x07
+#define SLEW_DIV_SHIFT         8
+#define SLEW_SYSDIV            0x0f
+#define SLEW_SYSDIV_SHIFT      20
+
+/* Clock Poll Timeout */
+#define LOCK_TIMEOUT_US         USEC_PER_MSEC
+
+/* SoC specific clock needed during SPLL clock rate switch */
+static struct clk_hw *pic32_sclk_hw;
+
+/* add instruction pipeline delay while CPU clock is in-transition. */
+#define cpu_nop5()                     \
+do {                                   \
+       __asm__ __volatile__("nop");    \
+       __asm__ __volatile__("nop");    \
+       __asm__ __volatile__("nop");    \
+       __asm__ __volatile__("nop");    \
+       __asm__ __volatile__("nop");    \
+} while (0)
+
+/* Perpheral bus clocks */
+struct pic32_periph_clk {
+       struct clk_hw hw;
+       void __iomem *ctrl_reg;
+       struct pic32_clk_common *core;
+};
+
+#define clkhw_to_pbclk(_hw)    container_of(_hw, struct pic32_periph_clk, hw)
+
+static int pbclk_is_enabled(struct clk_hw *hw)
+{
+       struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+       return readl(pb->ctrl_reg) & PB_DIV_ENABLE;
+}
+
+static int pbclk_enable(struct clk_hw *hw)
+{
+       struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+       writel(PB_DIV_ENABLE, PIC32_SET(pb->ctrl_reg));
+       return 0;
+}
+
+static void pbclk_disable(struct clk_hw *hw)
+{
+       struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+       writel(PB_DIV_ENABLE, PIC32_CLR(pb->ctrl_reg));
+}
+
+static unsigned long calc_best_divided_rate(unsigned long rate,
+                                           unsigned long parent_rate,
+                                           u32 divider_max,
+                                           u32 divider_min)
+{
+       unsigned long divided_rate, divided_rate_down, best_rate;
+       unsigned long div, div_up;
+
+       /* eq. clk_rate = parent_rate / divider.
+        *
+        * Find best divider to produce closest of target divided rate.
+        */
+       div = parent_rate / rate;
+       div = clamp_val(div, divider_min, divider_max);
+       div_up = clamp_val(div + 1, divider_min, divider_max);
+
+       divided_rate = parent_rate / div;
+       divided_rate_down = parent_rate / div_up;
+       if (abs(rate - divided_rate_down) < abs(rate - divided_rate))
+               best_rate = divided_rate_down;
+       else
+               best_rate = divided_rate;
+
+       return best_rate;
+}
+
+static inline u32 pbclk_read_pbdiv(struct pic32_periph_clk *pb)
+{
+       return ((readl(pb->ctrl_reg) >> PB_DIV_SHIFT) & PB_DIV_MASK) + 1;
+}
+
+static unsigned long pbclk_recalc_rate(struct clk_hw *hw,
+                                      unsigned long parent_rate)
+{
+       struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+       return parent_rate / pbclk_read_pbdiv(pb);
+}
+
+static long pbclk_round_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long *parent_rate)
+{
+       return calc_best_divided_rate(rate, *parent_rate,
+                                     PB_DIV_MAX, PB_DIV_MIN);
+}
+
+static int pbclk_set_rate(struct clk_hw *hw, unsigned long rate,
+                         unsigned long parent_rate)
+{
+       struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+       unsigned long flags;
+       u32 v, div;
+       int err;
+
+       /* check & wait for DIV_READY */
+       err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY,
+                                1, LOCK_TIMEOUT_US);
+       if (err)
+               return err;
+
+       /* calculate clkdiv and best rate */
+       div = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+       spin_lock_irqsave(&pb->core->reg_lock, flags);
+
+       /* apply new div */
+       v = readl(pb->ctrl_reg);
+       v &= ~PB_DIV_MASK;
+       v |= (div - 1);
+
+       pic32_syskey_unlock();
+
+       writel(v, pb->ctrl_reg);
+
+       spin_unlock_irqrestore(&pb->core->reg_lock, flags);
+
+       /* wait again, for pbdivready */
+       err = readl_poll_timeout_atomic(pb->ctrl_reg, v, v & PB_DIV_READY,
+                                       1, LOCK_TIMEOUT_US);
+       if (err)
+               return err;
+
+       /* confirm that new div is applied correctly */
+       return (pbclk_read_pbdiv(pb) == div) ? 0 : -EBUSY;
+}
+
+const struct clk_ops pic32_pbclk_ops = {
+       .enable         = pbclk_enable,
+       .disable        = pbclk_disable,
+       .is_enabled     = pbclk_is_enabled,
+       .recalc_rate    = pbclk_recalc_rate,
+       .round_rate     = pbclk_round_rate,
+       .set_rate       = pbclk_set_rate,
+};
+
+struct clk *pic32_periph_clk_register(const struct pic32_periph_clk_data *desc,
+                                     struct pic32_clk_common *core)
+{
+       struct pic32_periph_clk *pbclk;
+       struct clk *clk;
+
+       pbclk = devm_kzalloc(core->dev, sizeof(*pbclk), GFP_KERNEL);
+       if (!pbclk)
+               return ERR_PTR(-ENOMEM);
+
+       pbclk->hw.init = &desc->init_data;
+       pbclk->core = core;
+       pbclk->ctrl_reg = desc->ctrl_reg + core->iobase;
+
+       clk = devm_clk_register(core->dev, &pbclk->hw);
+       if (IS_ERR(clk)) {
+               dev_err(core->dev, "%s: clk_register() failed\n", __func__);
+               devm_kfree(core->dev, pbclk);
+       }
+
+       return clk;
+}
+
+/* Reference oscillator operations */
+struct pic32_ref_osc {
+       struct clk_hw hw;
+       void __iomem *ctrl_reg;
+       const u32 *parent_map;
+       struct pic32_clk_common *core;
+};
+
+#define clkhw_to_refosc(_hw)   container_of(_hw, struct pic32_ref_osc, hw)
+
+static int roclk_is_enabled(struct clk_hw *hw)
+{
+       struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+
+       return readl(refo->ctrl_reg) & REFO_ON;
+}
+
+static int roclk_enable(struct clk_hw *hw)
+{
+       struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+
+       writel(REFO_ON | REFO_OE, PIC32_SET(refo->ctrl_reg));
+       return 0;
+}
+
+static void roclk_disable(struct clk_hw *hw)
+{
+       struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+
+       writel(REFO_ON | REFO_OE, PIC32_CLR(refo->ctrl_reg));
+}
+
+static void roclk_init(struct clk_hw *hw)
+{
+       /* initialize clock in disabled state */
+       roclk_disable(hw);
+}
+
+static u8 roclk_get_parent(struct clk_hw *hw)
+{
+       struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+       u32 v, i;
+
+       v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK;
+
+       if (!refo->parent_map)
+               return v;
+
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++)
+               if (refo->parent_map[i] == v)
+                       return i;
+
+       return -EINVAL;
+}
+
+static unsigned long roclk_calc_rate(unsigned long parent_rate,
+                                    u32 rodiv, u32 rotrim)
+{
+       u64 rate64;
+
+       /* fout = fin / [2 * {div + (trim / 512)}]
+        *      = fin * 512 / [1024 * div + 2 * trim]
+        *      = fin * 256 / (512 * div + trim)
+        *      = (fin << 8) / ((div << 9) + trim)
+        */
+       if (rotrim) {
+               rodiv = (rodiv << 9) + rotrim;
+               rate64 = parent_rate;
+               rate64 <<= 8;
+               do_div(rate64, rodiv);
+       } else if (rodiv) {
+               rate64 = parent_rate / (rodiv << 1);
+       } else {
+               rate64 = parent_rate;
+       }
+       return rate64;
+}
+
+static void roclk_calc_div_trim(unsigned long rate,
+                               unsigned long parent_rate,
+                               u32 *rodiv_p, u32 *rotrim_p)
+{
+       u32 div, rotrim, rodiv;
+       u64 frac;
+
+       /* Find integer approximation of floating-point arithmetic.
+        *      fout = fin / [2 * {rodiv + (rotrim / 512)}] ... (1)
+        * i.e. fout = fin / 2 * DIV
+        *      whereas DIV = rodiv + (rotrim / 512)
+        *
+        * Since kernel does not perform floating-point arithmatic so
+        * (rotrim/512) will be zero. And DIV & rodiv will result same.
+        *
+        * ie. fout = (fin * 256) / [(512 * rodiv) + rotrim]  ... from (1)
+        * ie. rotrim = ((fin * 256) / fout) - (512 * DIV)
+        */
+       if (parent_rate <= rate) {
+               div = 0;
+               frac = 0;
+               rodiv = 0;
+               rotrim = 0;
+       } else {
+               div = parent_rate / (rate << 1);
+               frac = parent_rate;
+               frac <<= 8;
+               do_div(frac, rate);
+               frac -= (u64)(div << 9);
+
+               rodiv = (div > REFO_DIV_MASK) ? REFO_DIV_MASK : div;
+               rotrim = (frac >= REFO_TRIM_MAX) ? REFO_TRIM_MAX : frac;
+       }
+
+       if (rodiv_p)
+               *rodiv_p = rodiv;
+
+       if (rotrim_p)
+               *rotrim_p = rotrim;
+}
+
+static unsigned long roclk_recalc_rate(struct clk_hw *hw,
+                                      unsigned long parent_rate)
+{
+       struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+       u32 v, rodiv, rotrim;
+
+       /* get rodiv */
+       v = readl(refo->ctrl_reg);
+       rodiv = (v >> REFO_DIV_SHIFT) & REFO_DIV_MASK;
+
+       /* get trim */
+       v = readl(refo->ctrl_reg + REFO_TRIM_REG);
+       rotrim = (v >> REFO_TRIM_SHIFT) & REFO_TRIM_MASK;
+
+       return roclk_calc_rate(parent_rate, rodiv, rotrim);
+}
+
+static long roclk_round_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long *parent_rate)
+{
+       u32 rotrim, rodiv;
+
+       /* calculate dividers for new rate */
+       roclk_calc_div_trim(rate, *parent_rate, &rodiv, &rotrim);
+
+       /* caclulate new rate (rounding) based on new rodiv & rotrim */
+       return roclk_calc_rate(*parent_rate, rodiv, rotrim);
+}
+
+static int roclk_determine_rate(struct clk_hw *hw,
+                               struct clk_rate_request *req)
+{
+       struct clk_hw *parent_clk, *best_parent_clk = NULL;
+       unsigned int i, delta, best_delta = -1;
+       unsigned long parent_rate, best_parent_rate = 0;
+       unsigned long best = 0, nearest_rate;
+
+       /* find a parent which can generate nearest clkrate >= rate */
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+               /* get parent */
+               parent_clk = clk_hw_get_parent_by_index(hw, i);
+               if (!parent_clk)
+                       continue;
+
+               /* skip if parent runs slower than target rate */
+               parent_rate = clk_hw_get_rate(parent_clk);
+               if (req->rate > parent_rate)
+                       continue;
+
+               nearest_rate = roclk_round_rate(hw, req->rate, &parent_rate);
+               delta = abs(nearest_rate - req->rate);
+               if ((nearest_rate >= req->rate) && (delta < best_delta)) {
+                       best_parent_clk = parent_clk;
+                       best_parent_rate = parent_rate;
+                       best = nearest_rate;
+                       best_delta = delta;
+
+                       if (delta == 0)
+                               break;
+               }
+       }
+
+       /* if no match found, retain old rate */
+       if (!best_parent_clk) {
+               pr_err("%s:%s, no parent found for rate %lu.\n",
+                      __func__, clk_hw_get_name(hw), req->rate);
+               return clk_hw_get_rate(hw);
+       }
+
+       pr_debug("%s,rate %lu, best_parent(%s, %lu), best %lu, delta %d\n",
+                clk_hw_get_name(hw), req->rate,
+                clk_hw_get_name(best_parent_clk), best_parent_rate,
+                best, best_delta);
+
+       if (req->best_parent_rate)
+               req->best_parent_rate = best_parent_rate;
+
+       if (req->best_parent_hw)
+               req->best_parent_hw = best_parent_clk;
+
+       return best;
+}
+
+static int roclk_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+       unsigned long flags;
+       u32 v;
+       int err;
+
+       if (refo->parent_map)
+               index = refo->parent_map[index];
+
+       /* wait until ACTIVE bit is zero or timeout */
+       err = readl_poll_timeout(refo->ctrl_reg, v, !(v & REFO_ACTIVE),
+                                1, LOCK_TIMEOUT_US);
+       if (err) {
+               pr_err("%s: poll failed, clk active\n", clk_hw_get_name(hw));
+               return err;
+       }
+
+       spin_lock_irqsave(&refo->core->reg_lock, flags);
+
+       pic32_syskey_unlock();
+
+       /* calculate & apply new */
+       v = readl(refo->ctrl_reg);
+       v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
+       v |= index << REFO_SEL_SHIFT;
+
+       writel(v, refo->ctrl_reg);
+
+       spin_unlock_irqrestore(&refo->core->reg_lock, flags);
+
+       return 0;
+}
+
+static int roclk_set_rate_and_parent(struct clk_hw *hw,
+                                    unsigned long rate,
+                                    unsigned long parent_rate,
+                                    u8 index)
+{
+       struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+       unsigned long flags;
+       u32 trim, rodiv, v;
+       int err;
+
+       /* calculate new rodiv & rotrim for new rate */
+       roclk_calc_div_trim(rate, parent_rate, &rodiv, &trim);
+
+       pr_debug("parent_rate = %lu, rate = %lu, div = %d, trim = %d\n",
+                parent_rate, rate, rodiv, trim);
+
+       /* wait till source change is active */
+       err = readl_poll_timeout(refo->ctrl_reg, v,
+                                !(v & (REFO_ACTIVE | REFO_DIVSW_EN)),
+                                1, LOCK_TIMEOUT_US);
+       if (err) {
+               pr_err("%s: poll timedout, clock is still active\n", __func__);
+               return err;
+       }
+
+       spin_lock_irqsave(&refo->core->reg_lock, flags);
+       v = readl(refo->ctrl_reg);
+
+       pic32_syskey_unlock();
+
+       /* apply parent, if required */
+       if (refo->parent_map)
+               index = refo->parent_map[index];
+
+       v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
+       v |= index << REFO_SEL_SHIFT;
+
+       /* apply RODIV */
+       v &= ~(REFO_DIV_MASK << REFO_DIV_SHIFT);
+       v |= rodiv << REFO_DIV_SHIFT;
+       writel(v, refo->ctrl_reg);
+
+       /* apply ROTRIM */
+       v = readl(refo->ctrl_reg + REFO_TRIM_REG);
+       v &= ~(REFO_TRIM_MASK << REFO_TRIM_SHIFT);
+       v |= trim << REFO_TRIM_SHIFT;
+       writel(v, refo->ctrl_reg + REFO_TRIM_REG);
+
+       /* enable & activate divider switching */
+       writel(REFO_ON | REFO_DIVSW_EN, PIC32_SET(refo->ctrl_reg));
+
+       /* wait till divswen is in-progress */
+       err = readl_poll_timeout_atomic(refo->ctrl_reg, v, !(v & REFO_DIVSW_EN),
+                                       1, LOCK_TIMEOUT_US);
+       /* leave the clk gated as it was */
+       writel(REFO_ON, PIC32_CLR(refo->ctrl_reg));
+
+       spin_unlock_irqrestore(&refo->core->reg_lock, flags);
+
+       return err;
+}
+
+static int roclk_set_rate(struct clk_hw *hw, unsigned long rate,
+                         unsigned long parent_rate)
+{
+       u8 index = roclk_get_parent(hw);
+
+       return roclk_set_rate_and_parent(hw, rate, parent_rate, index);
+}
+
+const struct clk_ops pic32_roclk_ops = {
+       .enable                 = roclk_enable,
+       .disable                = roclk_disable,
+       .is_enabled             = roclk_is_enabled,
+       .get_parent             = roclk_get_parent,
+       .set_parent             = roclk_set_parent,
+       .determine_rate         = roclk_determine_rate,
+       .recalc_rate            = roclk_recalc_rate,
+       .set_rate_and_parent    = roclk_set_rate_and_parent,
+       .set_rate               = roclk_set_rate,
+       .init                   = roclk_init,
+};
+
+struct clk *pic32_refo_clk_register(const struct pic32_ref_osc_data *data,
+                                   struct pic32_clk_common *core)
+{
+       struct pic32_ref_osc *refo;
+       struct clk *clk;
+
+       refo = devm_kzalloc(core->dev, sizeof(*refo), GFP_KERNEL);
+       if (!refo)
+               return ERR_PTR(-ENOMEM);
+
+       refo->core = core;
+       refo->hw.init = &data->init_data;
+       refo->ctrl_reg = data->ctrl_reg + core->iobase;
+       refo->parent_map = data->parent_map;
+
+       clk = devm_clk_register(core->dev, &refo->hw);
+       if (IS_ERR(clk))
+               dev_err(core->dev, "%s: clk_register() failed\n", __func__);
+
+       return clk;
+}
+
+struct pic32_sys_pll {
+       struct clk_hw hw;
+       void __iomem *ctrl_reg;
+       void __iomem *status_reg;
+       u32 lock_mask;
+       u32 idiv; /* PLL iclk divider, treated fixed */
+       struct pic32_clk_common *core;
+};
+
+#define clkhw_to_spll(_hw)     container_of(_hw, struct pic32_sys_pll, hw)
+
+static inline u32 spll_odiv_to_divider(u32 odiv)
+{
+       odiv = clamp_val(odiv, PLL_ODIV_MIN, PLL_ODIV_MAX);
+
+       return 1 << odiv;
+}
+
+static unsigned long spll_calc_mult_div(struct pic32_sys_pll *pll,
+                                       unsigned long rate,
+                                       unsigned long parent_rate,
+                                       u32 *mult_p, u32 *odiv_p)
+{
+       u32 mul, div, best_mul = 1, best_div = 1;
+       unsigned long new_rate, best_rate = rate;
+       unsigned int best_delta = -1, delta, match_found = 0;
+       u64 rate64;
+
+       parent_rate /= pll->idiv;
+
+       for (mul = 1; mul <= PLL_MULT_MAX; mul++) {
+               for (div = PLL_ODIV_MIN; div <= PLL_ODIV_MAX; div++) {
+                       rate64 = parent_rate;
+                       rate64 *= mul;
+                       do_div(rate64, 1 << div);
+                       new_rate = rate64;
+                       delta = abs(rate - new_rate);
+                       if ((new_rate >= rate) && (delta < best_delta)) {
+                               best_delta = delta;
+                               best_rate = new_rate;
+                               best_mul = mul;
+                               best_div = div;
+                               match_found = 1;
+                       }
+               }
+       }
+
+       if (!match_found) {
+               pr_warn("spll: no match found\n");
+               return 0;
+       }
+
+       pr_debug("rate %lu, par_rate %lu/mult %u, div %u, best_rate %lu\n",
+                rate, parent_rate, best_mul, best_div, best_rate);
+
+       if (mult_p)
+               *mult_p = best_mul - 1;
+
+       if (odiv_p)
+               *odiv_p = best_div;
+
+       return best_rate;
+}
+
+static unsigned long spll_clk_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       struct pic32_sys_pll *pll = clkhw_to_spll(hw);
+       unsigned long pll_in_rate;
+       u32 mult, odiv, div, v;
+       u64 rate64;
+
+       v = readl(pll->ctrl_reg);
+       odiv = ((v >> PLL_ODIV_SHIFT) & PLL_ODIV_MASK);
+       mult = ((v >> PLL_MULT_SHIFT) & PLL_MULT_MASK) + 1;
+       div = spll_odiv_to_divider(odiv);
+
+       /* pll_in_rate = parent_rate / idiv
+        * pll_out_rate = pll_in_rate * mult / div;
+        */
+       pll_in_rate = parent_rate / pll->idiv;
+       rate64 = pll_in_rate;
+       rate64 *= mult;
+       do_div(rate64, div);
+
+       return rate64;
+}
+
+static long spll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *parent_rate)
+{
+       struct pic32_sys_pll *pll = clkhw_to_spll(hw);
+
+       return spll_calc_mult_div(pll, rate, *parent_rate, NULL, NULL);
+}
+
+static int spll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long parent_rate)
+{
+       struct pic32_sys_pll *pll = clkhw_to_spll(hw);
+       unsigned long ret, flags;
+       u32 mult, odiv, v;
+       int err;
+
+       ret = spll_calc_mult_div(pll, rate, parent_rate, &mult, &odiv);
+       if (!ret)
+               return -EINVAL;
+
+       /*
+        * We can't change SPLL counters when it is in-active use
+        * by SYSCLK. So check before applying new counters/rate.
+        */
+
+       /* Is spll_clk active parent of sys_clk ? */
+       if (unlikely(clk_hw_get_parent(pic32_sclk_hw) == hw)) {
+               pr_err("%s: failed, clk in-use\n", __func__);
+               return -EBUSY;
+       }
+
+       spin_lock_irqsave(&pll->core->reg_lock, flags);
+
+       /* apply new multiplier & divisor */
+       v = readl(pll->ctrl_reg);
+       v &= ~(PLL_MULT_MASK << PLL_MULT_SHIFT);
+       v &= ~(PLL_ODIV_MASK << PLL_ODIV_SHIFT);
+       v |= (mult << PLL_MULT_SHIFT) | (odiv << PLL_ODIV_SHIFT);
+
+       /* sys unlock before write */
+       pic32_syskey_unlock();
+
+       writel(v, pll->ctrl_reg);
+       cpu_relax();
+
+       /* insert few nops (5-stage) to ensure CPU does not hang */
+       cpu_nop5();
+       cpu_nop5();
+
+       /* Wait until PLL is locked (maximum 100 usecs). */
+       err = readl_poll_timeout_atomic(pll->status_reg, v,
+                                       v & pll->lock_mask, 1, 100);
+       spin_unlock_irqrestore(&pll->core->reg_lock, flags);
+
+       return err;
+}
+
+/* SPLL clock operation */
+const struct clk_ops pic32_spll_ops = {
+       .recalc_rate    = spll_clk_recalc_rate,
+       .round_rate     = spll_clk_round_rate,
+       .set_rate       = spll_clk_set_rate,
+};
+
+struct clk *pic32_spll_clk_register(const struct pic32_sys_pll_data *data,
+                                   struct pic32_clk_common *core)
+{
+       struct pic32_sys_pll *spll;
+       struct clk *clk;
+
+       spll = devm_kzalloc(core->dev, sizeof(*spll), GFP_KERNEL);
+       if (!spll)
+               return ERR_PTR(-ENOMEM);
+
+       spll->core = core;
+       spll->hw.init = &data->init_data;
+       spll->ctrl_reg = data->ctrl_reg + core->iobase;
+       spll->status_reg = data->status_reg + core->iobase;
+       spll->lock_mask = data->lock_mask;
+
+       /* cache PLL idiv; PLL driver uses it as constant.*/
+       spll->idiv = (readl(spll->ctrl_reg) >> PLL_IDIV_SHIFT) & PLL_IDIV_MASK;
+       spll->idiv += 1;
+
+       clk = devm_clk_register(core->dev, &spll->hw);
+       if (IS_ERR(clk))
+               dev_err(core->dev, "sys_pll: clk_register() failed\n");
+
+       return clk;
+}
+
+/* System mux clock(aka SCLK) */
+
+struct pic32_sys_clk {
+       struct clk_hw hw;
+       void __iomem *mux_reg;
+       void __iomem *slew_reg;
+       u32 slew_div;
+       const u32 *parent_map;
+       struct pic32_clk_common *core;
+};
+
+#define clkhw_to_sys_clk(_hw)  container_of(_hw, struct pic32_sys_clk, hw)
+
+static unsigned long sclk_get_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+       struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+       u32 div;
+
+       div = (readl(sclk->slew_reg) >> SLEW_SYSDIV_SHIFT) & SLEW_SYSDIV;
+       div += 1; /* sys-div to divider */
+
+       return parent_rate / div;
+}
+
+static long sclk_round_rate(struct clk_hw *hw, unsigned long rate,
+                           unsigned long *parent_rate)
+{
+       return calc_best_divided_rate(rate, *parent_rate, SLEW_SYSDIV, 1);
+}
+
+static int sclk_set_rate(struct clk_hw *hw,
+                        unsigned long rate, unsigned long parent_rate)
+{
+       struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+       unsigned long flags;
+       u32 v, div;
+       int err;
+
+       div = parent_rate / rate;
+
+       spin_lock_irqsave(&sclk->core->reg_lock, flags);
+
+       /* apply new div */
+       v = readl(sclk->slew_reg);
+       v &= ~(SLEW_SYSDIV << SLEW_SYSDIV_SHIFT);
+       v |= (div - 1) << SLEW_SYSDIV_SHIFT;
+
+       pic32_syskey_unlock();
+
+       writel(v, sclk->slew_reg);
+
+       /* wait until BUSY is cleared */
+       err = readl_poll_timeout_atomic(sclk->slew_reg, v,
+                                       !(v & SLEW_BUSY), 1, LOCK_TIMEOUT_US);
+
+       spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
+
+       return err;
+}
+
+static u8 sclk_get_parent(struct clk_hw *hw)
+{
+       struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+       u32 i, v;
+
+       v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK;
+
+       if (!sclk->parent_map)
+               return v;
+
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++)
+               if (sclk->parent_map[i] == v)
+                       return i;
+       return -EINVAL;
+}
+
+static int sclk_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+       unsigned long flags;
+       u32 nosc, cosc, v;
+       int err;
+
+       spin_lock_irqsave(&sclk->core->reg_lock, flags);
+
+       /* find new_osc */
+       nosc = sclk->parent_map ? sclk->parent_map[index] : index;
+
+       /* set new parent */
+       v = readl(sclk->mux_reg);
+       v &= ~(OSC_NEW_MASK << OSC_NEW_SHIFT);
+       v |= nosc << OSC_NEW_SHIFT;
+
+       pic32_syskey_unlock();
+
+       writel(v, sclk->mux_reg);
+
+       /* initate switch */
+       writel(OSC_SWEN, PIC32_SET(sclk->mux_reg));
+       cpu_relax();
+
+       /* add nop to flush pipeline (as cpu_clk is in-flux) */
+       cpu_nop5();
+
+       /* wait for SWEN bit to clear */
+       err = readl_poll_timeout_atomic(sclk->slew_reg, v,
+                                       !(v & OSC_SWEN), 1, LOCK_TIMEOUT_US);
+
+       spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
+
+       /*
+        * SCLK clock-switching logic might reject a clock switching request
+        * if pre-requisites (like new clk_src not present or unstable) are
+        * not met.
+        * So confirm before claiming success.
+        */
+       cosc = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK;
+       if (cosc != nosc) {
+               pr_err("%s: err, failed to set_parent() to %d, current %d\n",
+                      clk_hw_get_name(hw), nosc, cosc);
+               err = -EBUSY;
+       }
+
+       return err;
+}
+
+static void sclk_init(struct clk_hw *hw)
+{
+       struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+       unsigned long flags;
+       u32 v;
+
+       /* Maintain reference to this clk, required in spll_clk_set_rate() */
+       pic32_sclk_hw = hw;
+
+       /* apply slew divider on both up and down scaling */
+       if (sclk->slew_div) {
+               spin_lock_irqsave(&sclk->core->reg_lock, flags);
+               v = readl(sclk->slew_reg);
+               v &= ~(SLEW_DIV << SLEW_DIV_SHIFT);
+               v |= sclk->slew_div << SLEW_DIV_SHIFT;
+               v |= SLEW_DOWNEN | SLEW_UPEN;
+               writel(v, sclk->slew_reg);
+               spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
+       }
+}
+
+/* sclk with post-divider */
+const struct clk_ops pic32_sclk_ops = {
+       .get_parent     = sclk_get_parent,
+       .set_parent     = sclk_set_parent,
+       .round_rate     = sclk_round_rate,
+       .set_rate       = sclk_set_rate,
+       .recalc_rate    = sclk_get_rate,
+       .init           = sclk_init,
+       .determine_rate = __clk_mux_determine_rate,
+};
+
+/* sclk with no slew and no post-divider */
+const struct clk_ops pic32_sclk_no_div_ops = {
+       .get_parent     = sclk_get_parent,
+       .set_parent     = sclk_set_parent,
+       .init           = sclk_init,
+       .determine_rate = __clk_mux_determine_rate,
+};
+
+struct clk *pic32_sys_clk_register(const struct pic32_sys_clk_data *data,
+                                  struct pic32_clk_common *core)
+{
+       struct pic32_sys_clk *sclk;
+       struct clk *clk;
+
+       sclk = devm_kzalloc(core->dev, sizeof(*sclk), GFP_KERNEL);
+       if (!sclk)
+               return ERR_PTR(-ENOMEM);
+
+       sclk->core = core;
+       sclk->hw.init = &data->init_data;
+       sclk->mux_reg = data->mux_reg + core->iobase;
+       sclk->slew_reg = data->slew_reg + core->iobase;
+       sclk->slew_div = data->slew_div;
+       sclk->parent_map = data->parent_map;
+
+       clk = devm_clk_register(core->dev, &sclk->hw);
+       if (IS_ERR(clk))
+               dev_err(core->dev, "%s: clk register failed\n", __func__);
+
+       return clk;
+}
+
+/* secondary oscillator */
+struct pic32_sec_osc {
+       struct clk_hw hw;
+       void __iomem *enable_reg;
+       void __iomem *status_reg;
+       u32 enable_mask;
+       u32 status_mask;
+       unsigned long fixed_rate;
+       struct pic32_clk_common *core;
+};
+
+#define clkhw_to_sosc(_hw)     container_of(_hw, struct pic32_sec_osc, hw)
+static int sosc_clk_enable(struct clk_hw *hw)
+{
+       struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
+       u32 v;
+
+       /* enable SOSC */
+       pic32_syskey_unlock();
+       writel(sosc->enable_mask, PIC32_SET(sosc->enable_reg));
+
+       /* wait till warm-up period expires or ready-status is updated */
+       return readl_poll_timeout_atomic(sosc->status_reg, v,
+                                        v & sosc->status_mask, 1, 100);
+}
+
+static void sosc_clk_disable(struct clk_hw *hw)
+{
+       struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
+
+       pic32_syskey_unlock();
+       writel(sosc->enable_mask, PIC32_CLR(sosc->enable_reg));
+}
+
+static int sosc_clk_is_enabled(struct clk_hw *hw)
+{
+       struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
+       u32 enabled, ready;
+
+       /* check enabled and ready status */
+       enabled = readl(sosc->enable_reg) & sosc->enable_mask;
+       ready = readl(sosc->status_reg) & sosc->status_mask;
+
+       return enabled && ready;
+}
+
+static unsigned long sosc_clk_calc_rate(struct clk_hw *hw,
+                                       unsigned long parent_rate)
+{
+       return clkhw_to_sosc(hw)->fixed_rate;
+}
+
+const struct clk_ops pic32_sosc_ops = {
+       .enable = sosc_clk_enable,
+       .disable = sosc_clk_disable,
+       .is_enabled = sosc_clk_is_enabled,
+       .recalc_rate = sosc_clk_calc_rate,
+};
+
+struct clk *pic32_sosc_clk_register(const struct pic32_sec_osc_data *data,
+                                   struct pic32_clk_common *core)
+{
+       struct pic32_sec_osc *sosc;
+
+       sosc = devm_kzalloc(core->dev, sizeof(*sosc), GFP_KERNEL);
+       if (!sosc)
+               return ERR_PTR(-ENOMEM);
+
+       sosc->core = core;
+       sosc->hw.init = &data->init_data;
+       sosc->fixed_rate = data->fixed_rate;
+       sosc->enable_mask = data->enable_mask;
+       sosc->status_mask = data->status_mask;
+       sosc->enable_reg = data->enable_reg + core->iobase;
+       sosc->status_reg = data->status_reg + core->iobase;
+
+       return devm_clk_register(core->dev, &sosc->hw);
+}
diff --git a/drivers/clk/microchip/clk-core.h b/drivers/clk/microchip/clk-core.h
new file mode 100644 (file)
index 0000000..8566642
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Purna Chandra Mandal,<purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology 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.
+ */
+#ifndef __MICROCHIP_CLK_PIC32_H_
+#define __MICROCHIP_CLK_PIC32_H_
+
+#include <linux/clk-provider.h>
+
+/* PIC32 clock data */
+struct pic32_clk_common {
+       struct device *dev;
+       void __iomem *iobase;
+       spinlock_t reg_lock; /* clock lock */
+};
+
+/* System PLL clock */
+struct pic32_sys_pll_data {
+       struct clk_init_data init_data;
+       const u32 ctrl_reg;
+       const u32 status_reg;
+       const u32 lock_mask;
+};
+
+/* System clock */
+struct pic32_sys_clk_data {
+       struct clk_init_data init_data;
+       const u32 mux_reg;
+       const u32 slew_reg;
+       const u32 *parent_map;
+       const u32 slew_div;
+};
+
+/* Reference Oscillator clock */
+struct pic32_ref_osc_data {
+       struct clk_init_data init_data;
+       const u32 ctrl_reg;
+       const u32 *parent_map;
+};
+
+/* Peripheral Bus clock */
+struct pic32_periph_clk_data {
+       struct clk_init_data init_data;
+       const u32 ctrl_reg;
+};
+
+/* External Secondary Oscillator clock  */
+struct pic32_sec_osc_data {
+       struct clk_init_data init_data;
+       const u32 enable_reg;
+       const u32 status_reg;
+       const u32 enable_mask;
+       const u32 status_mask;
+       const unsigned long fixed_rate;
+};
+
+extern const struct clk_ops pic32_pbclk_ops;
+extern const struct clk_ops pic32_sclk_ops;
+extern const struct clk_ops pic32_sclk_no_div_ops;
+extern const struct clk_ops pic32_spll_ops;
+extern const struct clk_ops pic32_roclk_ops;
+extern const struct clk_ops pic32_sosc_ops;
+
+struct clk *pic32_periph_clk_register(const struct pic32_periph_clk_data *data,
+                                     struct pic32_clk_common *core);
+struct clk *pic32_refo_clk_register(const struct pic32_ref_osc_data *data,
+                                   struct pic32_clk_common *core);
+struct clk *pic32_sys_clk_register(const struct pic32_sys_clk_data *data,
+                                  struct pic32_clk_common *core);
+struct clk *pic32_spll_clk_register(const struct pic32_sys_pll_data *data,
+                                   struct pic32_clk_common *core);
+struct clk *pic32_sosc_clk_register(const struct pic32_sec_osc_data *data,
+                                   struct pic32_clk_common *core);
+
+#endif /* __MICROCHIP_CLK_PIC32_H_*/
diff --git a/drivers/clk/microchip/clk-pic32mzda.c b/drivers/clk/microchip/clk-pic32mzda.c
new file mode 100644 (file)
index 0000000..020a29a
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Purna Chandra Mandal,<purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology 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.
+ */
+#include <dt-bindings/clock/microchip,pic32-clock.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <asm/traps.h>
+
+#include "clk-core.h"
+
+/* FRC Postscaler */
+#define OSC_FRCDIV_MASK                0x07
+#define OSC_FRCDIV_SHIFT       24
+
+/* SPLL fields */
+#define PLL_ICLK_MASK          0x01
+#define PLL_ICLK_SHIFT         7
+
+#define DECLARE_PERIPHERAL_CLOCK(__clk_name, __reg, __flags)   \
+       {                                                       \
+               .ctrl_reg = (__reg),                            \
+               .init_data = {                                  \
+                       .name = (__clk_name),                   \
+                       .parent_names = (const char *[]) {      \
+                               "sys_clk"                       \
+                       },                                      \
+                       .num_parents = 1,                       \
+                       .ops = &pic32_pbclk_ops,                \
+                       .flags = (__flags),                     \
+               },                                              \
+       }
+
+#define DECLARE_REFO_CLOCK(__clkid, __reg)                             \
+       {                                                               \
+               .ctrl_reg = (__reg),                                    \
+               .init_data = {                                          \
+                       .name = "refo" #__clkid "_clk",                 \
+                       .parent_names = (const char *[]) {              \
+                               "sys_clk", "pb1_clk", "posc_clk",       \
+                               "frc_clk", "lprc_clk", "sosc_clk",      \
+                               "sys_pll", "refi" #__clkid "_clk",      \
+                               "bfrc_clk",                             \
+                       },                                              \
+                       .num_parents = 9,                               \
+                       .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,\
+                       .ops = &pic32_roclk_ops,                        \
+               },                                                      \
+               .parent_map = (const u32[]) {                           \
+                       0, 1, 2, 3, 4, 5, 7, 8, 9                       \
+               },                                                      \
+       }
+
+static const struct pic32_ref_osc_data ref_clks[] = {
+       DECLARE_REFO_CLOCK(1, 0x80),
+       DECLARE_REFO_CLOCK(2, 0xa0),
+       DECLARE_REFO_CLOCK(3, 0xc0),
+       DECLARE_REFO_CLOCK(4, 0xe0),
+       DECLARE_REFO_CLOCK(5, 0x100),
+};
+
+static const struct pic32_periph_clk_data periph_clocks[] = {
+       DECLARE_PERIPHERAL_CLOCK("pb1_clk", 0x140, 0),
+       DECLARE_PERIPHERAL_CLOCK("pb2_clk", 0x150, CLK_IGNORE_UNUSED),
+       DECLARE_PERIPHERAL_CLOCK("pb3_clk", 0x160, 0),
+       DECLARE_PERIPHERAL_CLOCK("pb4_clk", 0x170, 0),
+       DECLARE_PERIPHERAL_CLOCK("pb5_clk", 0x180, 0),
+       DECLARE_PERIPHERAL_CLOCK("pb6_clk", 0x190, 0),
+       DECLARE_PERIPHERAL_CLOCK("cpu_clk", 0x1a0, CLK_IGNORE_UNUSED),
+};
+
+static const struct pic32_sys_clk_data sys_mux_clk = {
+       .slew_reg = 0x1c0,
+       .slew_div = 2, /* step of div_4 -> div_2 -> no_div */
+       .init_data = {
+               .name = "sys_clk",
+               .parent_names = (const char *[]) {
+                       "frcdiv_clk", "sys_pll", "posc_clk",
+                       "sosc_clk", "lprc_clk", "frcdiv_clk",
+               },
+               .num_parents = 6,
+               .ops = &pic32_sclk_ops,
+       },
+       .parent_map = (const u32[]) {
+               0, 1, 2, 4, 5, 7,
+       },
+};
+
+static const struct pic32_sys_pll_data sys_pll = {
+       .ctrl_reg = 0x020,
+       .status_reg = 0x1d0,
+       .lock_mask = BIT(7),
+       .init_data = {
+               .name = "sys_pll",
+               .parent_names = (const char *[]) {
+                       "spll_mux_clk"
+               },
+               .num_parents = 1,
+               .ops = &pic32_spll_ops,
+       },
+};
+
+static const struct pic32_sec_osc_data sosc_clk = {
+       .status_reg = 0x1d0,
+       .enable_mask = BIT(1),
+       .status_mask = BIT(4),
+       .init_data = {
+               .name = "sosc_clk",
+               .parent_names = NULL,
+               .ops = &pic32_sosc_ops,
+       },
+};
+
+static int pic32mzda_critical_clks[] = {
+       PB2CLK, PB7CLK
+};
+
+/* PIC32MZDA clock data */
+struct pic32mzda_clk_data {
+       struct clk *clks[MAXCLKS];
+       struct pic32_clk_common core;
+       struct clk_onecell_data onecell_data;
+       struct notifier_block failsafe_notifier;
+};
+
+static int pic32_fscm_nmi(struct notifier_block *nb,
+                         unsigned long action, void *data)
+{
+       struct pic32mzda_clk_data *cd;
+
+       cd  = container_of(nb, struct pic32mzda_clk_data, failsafe_notifier);
+
+       /* SYSCLK is now running from BFRCCLK. Report clock failure. */
+       if (readl(cd->core.iobase) & BIT(2))
+               pr_alert("pic32-clk: FSCM detected clk failure.\n");
+
+       /* TODO: detect reason of failure and recover accordingly */
+
+       return NOTIFY_OK;
+}
+
+static int pic32mzda_clk_probe(struct platform_device *pdev)
+{
+       const char *const pll_mux_parents[] = {"posc_clk", "frc_clk"};
+       struct device_node *np = pdev->dev.of_node;
+       struct pic32mzda_clk_data *cd;
+       struct pic32_clk_common *core;
+       struct clk *pll_mux_clk, *clk;
+       struct clk **clks;
+       int nr_clks, i, ret;
+
+       cd = devm_kzalloc(&pdev->dev, sizeof(*cd), GFP_KERNEL);
+       if (!cd)
+               return -ENOMEM;
+
+       core = &cd->core;
+       core->iobase = of_io_request_and_map(np, 0, of_node_full_name(np));
+       if (IS_ERR(core->iobase)) {
+               dev_err(&pdev->dev, "pic32-clk: failed to map registers\n");
+               return PTR_ERR(core->iobase);
+       }
+
+       spin_lock_init(&core->reg_lock);
+       core->dev = &pdev->dev;
+       clks = &cd->clks[0];
+
+       /* register fixed rate clocks */
+       clks[POSCCLK] = clk_register_fixed_rate(&pdev->dev, "posc_clk", NULL,
+                                               CLK_IS_ROOT, 24000000);
+       clks[FRCCLK] =  clk_register_fixed_rate(&pdev->dev, "frc_clk", NULL,
+                                               CLK_IS_ROOT, 8000000);
+       clks[BFRCCLK] = clk_register_fixed_rate(&pdev->dev, "bfrc_clk", NULL,
+                                               CLK_IS_ROOT, 8000000);
+       clks[LPRCCLK] = clk_register_fixed_rate(&pdev->dev, "lprc_clk", NULL,
+                                               CLK_IS_ROOT, 32000);
+       clks[UPLLCLK] = clk_register_fixed_rate(&pdev->dev, "usbphy_clk", NULL,
+                                               CLK_IS_ROOT, 24000000);
+       /* fixed rate (optional) clock */
+       if (of_find_property(np, "microchip,pic32mzda-sosc", NULL)) {
+               pr_info("pic32-clk: dt requests SOSC.\n");
+               clks[SOSCCLK] = pic32_sosc_clk_register(&sosc_clk, core);
+       }
+       /* divider clock */
+       clks[FRCDIVCLK] = clk_register_divider(&pdev->dev, "frcdiv_clk",
+                                              "frc_clk", 0,
+                                              core->iobase,
+                                              OSC_FRCDIV_SHIFT,
+                                              OSC_FRCDIV_MASK,
+                                              CLK_DIVIDER_POWER_OF_TWO,
+                                              &core->reg_lock);
+       /* PLL ICLK mux */
+       pll_mux_clk = clk_register_mux(&pdev->dev, "spll_mux_clk",
+                                      pll_mux_parents, 2, 0,
+                                      core->iobase + 0x020,
+                                      PLL_ICLK_SHIFT, 1, 0, &core->reg_lock);
+       if (IS_ERR(pll_mux_clk))
+               pr_err("spll_mux_clk: clk register failed\n");
+
+       /* PLL */
+       clks[PLLCLK] = pic32_spll_clk_register(&sys_pll, core);
+       /* SYSTEM clock */
+       clks[SCLK] = pic32_sys_clk_register(&sys_mux_clk, core);
+       /* Peripheral bus clocks */
+       for (nr_clks = PB1CLK, i = 0; nr_clks <= PB7CLK; i++, nr_clks++)
+               clks[nr_clks] = pic32_periph_clk_register(&periph_clocks[i],
+                                                         core);
+       /* Reference oscillator clock */
+       for (nr_clks = REF1CLK, i = 0; nr_clks <= REF5CLK; i++, nr_clks++)
+               clks[nr_clks] = pic32_refo_clk_register(&ref_clks[i], core);
+
+       /* register clkdev */
+       for (i = 0; i < MAXCLKS; i++) {
+               if (IS_ERR(clks[i]))
+                       continue;
+               clk_register_clkdev(clks[i], NULL, __clk_get_name(clks[i]));
+       }
+
+       /* register clock provider */
+       cd->onecell_data.clks = clks;
+       cd->onecell_data.clk_num = MAXCLKS;
+       ret = of_clk_add_provider(np, of_clk_src_onecell_get,
+                                 &cd->onecell_data);
+       if (ret)
+               return ret;
+
+       /* force enable critical clocks */
+       for (i = 0; i < ARRAY_SIZE(pic32mzda_critical_clks); i++) {
+               clk = clks[pic32mzda_critical_clks[i]];
+               if (clk_prepare_enable(clk))
+                       dev_err(&pdev->dev, "clk_prepare_enable(%s) failed\n",
+                               __clk_get_name(clk));
+       }
+
+       /* register NMI for failsafe clock monitor */
+       cd->failsafe_notifier.notifier_call = pic32_fscm_nmi;
+       return register_nmi_notifier(&cd->failsafe_notifier);
+}
+
+static const struct of_device_id pic32mzda_clk_match_table[] = {
+       { .compatible = "microchip,pic32mzda-clk", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, pic32mzda_clk_match_table);
+
+static struct platform_driver pic32mzda_clk_driver = {
+       .probe          = pic32mzda_clk_probe,
+       .driver         = {
+               .name   = "clk-pic32mzda",
+               .of_match_table = pic32mzda_clk_match_table,
+       },
+};
+
+static int __init microchip_pic32mzda_clk_init(void)
+{
+       return platform_driver_register(&pic32mzda_clk_driver);
+}
+core_initcall(microchip_pic32mzda_clk_init);
+
+MODULE_DESCRIPTION("Microchip PIC32MZDA Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:clk-pic32mzda");
index e1eb11ee35708049bc19063de73e977981251c14..0a9b6a093646bd1dd60ee092e362b24527f0ef1e 100644 (file)
@@ -102,7 +102,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3)             += cris-artpec3-cpufreq.o
 obj-$(CONFIG_ETRAXFS)                  += cris-etraxfs-cpufreq.o
 obj-$(CONFIG_IA64_ACPI_CPUFREQ)                += ia64-acpi-cpufreq.o
 obj-$(CONFIG_LOONGSON2_CPUFREQ)                += loongson2_cpufreq.o
-obj-$(CONFIG_LOONGSON1_CPUFREQ)                += ls1x-cpufreq.o
+obj-$(CONFIG_LOONGSON1_CPUFREQ)                += loongson1-cpufreq.o
 obj-$(CONFIG_SH_CPU_FREQ)              += sh-cpufreq.o
 obj-$(CONFIG_SPARC_US2E_CPUFREQ)       += sparc-us2e-cpufreq.o
 obj-$(CONFIG_SPARC_US3_CPUFREQ)                += sparc-us3-cpufreq.o
similarity index 65%
rename from drivers/cpufreq/ls1x-cpufreq.c
rename to drivers/cpufreq/loongson1-cpufreq.c
index 262581b3318d7913380fef95facb9e191dff43d4..be89416e2358fcbb0464e525421f7f6607d1883b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * CPU Frequency Scaling for Loongson 1 SoC
  *
- * Copyright (C) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (C) 2014-2016 Zhang, Keguang <keguang.zhang@gmail.com>
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
@@ -20,7 +20,7 @@
 #include <cpufreq.h>
 #include <loongson1.h>
 
-static struct {
+struct ls1x_cpufreq {
        struct device *dev;
        struct clk *clk;        /* CPU clk */
        struct clk *mux_clk;    /* MUX of CPU clk */
@@ -28,7 +28,9 @@ static struct {
        struct clk *osc_clk;    /* OSC clk */
        unsigned int max_freq;
        unsigned int min_freq;
-} ls1x_cpufreq;
+};
+
+static struct ls1x_cpufreq *cpufreq;
 
 static int ls1x_cpufreq_notifier(struct notifier_block *nb,
                                 unsigned long val, void *data)
@@ -46,6 +48,7 @@ static struct notifier_block ls1x_cpufreq_notifier_block = {
 static int ls1x_cpufreq_target(struct cpufreq_policy *policy,
                               unsigned int index)
 {
+       struct device *cpu_dev = get_cpu_device(policy->cpu);
        unsigned int old_freq, new_freq;
 
        old_freq = policy->cur;
@@ -60,53 +63,49 @@ static int ls1x_cpufreq_target(struct cpufreq_policy *policy,
         *  - Reparent CPU clk back to CPU DIV clk
         */
 
-       dev_dbg(ls1x_cpufreq.dev, "%u KHz --> %u KHz\n", old_freq, new_freq);
-       clk_set_parent(policy->clk, ls1x_cpufreq.osc_clk);
+       clk_set_parent(policy->clk, cpufreq->osc_clk);
        __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU,
                     LS1X_CLK_PLL_DIV);
        __raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU),
                     LS1X_CLK_PLL_DIV);
-       clk_set_rate(ls1x_cpufreq.mux_clk, new_freq * 1000);
-       clk_set_parent(policy->clk, ls1x_cpufreq.mux_clk);
+       clk_set_rate(cpufreq->mux_clk, new_freq * 1000);
+       clk_set_parent(policy->clk, cpufreq->mux_clk);
+       dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq);
 
        return 0;
 }
 
 static int ls1x_cpufreq_init(struct cpufreq_policy *policy)
 {
+       struct device *cpu_dev = get_cpu_device(policy->cpu);
        struct cpufreq_frequency_table *freq_tbl;
        unsigned int pll_freq, freq;
        int steps, i, ret;
 
-       pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000;
+       pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000;
 
        steps = 1 << DIV_CPU_WIDTH;
-       freq_tbl = kzalloc(sizeof(*freq_tbl) * steps, GFP_KERNEL);
-       if (!freq_tbl) {
-               dev_err(ls1x_cpufreq.dev,
-                       "failed to alloc cpufreq_frequency_table\n");
-               ret = -ENOMEM;
-               goto out;
-       }
+       freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL);
+       if (!freq_tbl)
+               return -ENOMEM;
 
        for (i = 0; i < (steps - 1); i++) {
                freq = pll_freq / (i + 1);
-               if ((freq < ls1x_cpufreq.min_freq) ||
-                   (freq > ls1x_cpufreq.max_freq))
+               if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq))
                        freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID;
                else
                        freq_tbl[i].frequency = freq;
-               dev_dbg(ls1x_cpufreq.dev,
+               dev_dbg(cpu_dev,
                        "cpufreq table: index %d: frequency %d\n", i,
                        freq_tbl[i].frequency);
        }
        freq_tbl[i].frequency = CPUFREQ_TABLE_END;
 
-       policy->clk = ls1x_cpufreq.clk;
+       policy->clk = cpufreq->clk;
        ret = cpufreq_generic_init(policy, freq_tbl, 0);
        if (ret)
                kfree(freq_tbl);
-out:
+
        return ret;
 }
 
@@ -138,85 +137,86 @@ static int ls1x_cpufreq_remove(struct platform_device *pdev)
 
 static int ls1x_cpufreq_probe(struct platform_device *pdev)
 {
-       struct plat_ls1x_cpufreq *pdata = pdev->dev.platform_data;
+       struct plat_ls1x_cpufreq *pdata = dev_get_platdata(&pdev->dev);
        struct clk *clk;
        int ret;
 
-       if (!pdata || !pdata->clk_name || !pdata->osc_clk_name)
+       if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) {
+               dev_err(&pdev->dev, "platform data missing\n");
                return -EINVAL;
+       }
 
-       ls1x_cpufreq.dev = &pdev->dev;
+       cpufreq =
+           devm_kzalloc(&pdev->dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL);
+       if (!cpufreq)
+               return -ENOMEM;
+
+       cpufreq->dev = &pdev->dev;
 
        clk = devm_clk_get(&pdev->dev, pdata->clk_name);
        if (IS_ERR(clk)) {
-               dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n",
+               dev_err(&pdev->dev, "unable to get %s clock\n",
                        pdata->clk_name);
-               ret = PTR_ERR(clk);
-               goto out;
+               return PTR_ERR(clk);
        }
-       ls1x_cpufreq.clk = clk;
+       cpufreq->clk = clk;
 
        clk = clk_get_parent(clk);
        if (IS_ERR(clk)) {
-               dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n",
-                       __clk_get_name(ls1x_cpufreq.clk));
-               ret = PTR_ERR(clk);
-               goto out;
+               dev_err(&pdev->dev, "unable to get parent of %s clock\n",
+                       __clk_get_name(cpufreq->clk));
+               return PTR_ERR(clk);
        }
-       ls1x_cpufreq.mux_clk = clk;
+       cpufreq->mux_clk = clk;
 
        clk = clk_get_parent(clk);
        if (IS_ERR(clk)) {
-               dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n",
-                       __clk_get_name(ls1x_cpufreq.mux_clk));
-               ret = PTR_ERR(clk);
-               goto out;
+               dev_err(&pdev->dev, "unable to get parent of %s clock\n",
+                       __clk_get_name(cpufreq->mux_clk));
+               return PTR_ERR(clk);
        }
-       ls1x_cpufreq.pll_clk = clk;
+       cpufreq->pll_clk = clk;
 
        clk = devm_clk_get(&pdev->dev, pdata->osc_clk_name);
        if (IS_ERR(clk)) {
-               dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n",
+               dev_err(&pdev->dev, "unable to get %s clock\n",
                        pdata->osc_clk_name);
-               ret = PTR_ERR(clk);
-               goto out;
+               return PTR_ERR(clk);
        }
-       ls1x_cpufreq.osc_clk = clk;
+       cpufreq->osc_clk = clk;
 
-       ls1x_cpufreq.max_freq = pdata->max_freq;
-       ls1x_cpufreq.min_freq = pdata->min_freq;
+       cpufreq->max_freq = pdata->max_freq;
+       cpufreq->min_freq = pdata->min_freq;
 
        ret = cpufreq_register_driver(&ls1x_cpufreq_driver);
        if (ret) {
-               dev_err(ls1x_cpufreq.dev,
-                       "failed to register cpufreq driver: %d\n", ret);
-               goto out;
+               dev_err(&pdev->dev,
+                       "failed to register CPUFreq driver: %d\n", ret);
+               return ret;
        }
 
        ret = cpufreq_register_notifier(&ls1x_cpufreq_notifier_block,
                                        CPUFREQ_TRANSITION_NOTIFIER);
 
-       if (!ret)
-               goto out;
-
-       dev_err(ls1x_cpufreq.dev, "failed to register cpufreq notifier: %d\n",
-               ret);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "failed to register CPUFreq notifier: %d\n",ret);
+               cpufreq_unregister_driver(&ls1x_cpufreq_driver);
+       }
 
-       cpufreq_unregister_driver(&ls1x_cpufreq_driver);
-out:
        return ret;
 }
 
 static struct platform_driver ls1x_cpufreq_platdrv = {
-       .driver = {
+       .probe  = ls1x_cpufreq_probe,
+       .remove = ls1x_cpufreq_remove,
+       .driver = {
                .name   = "ls1x-cpufreq",
        },
-       .probe          = ls1x_cpufreq_probe,
-       .remove         = ls1x_cpufreq_remove,
 };
 
 module_platform_driver(ls1x_cpufreq_platdrv);
 
 MODULE_AUTHOR("Kelvin Cheung <keguang.zhang@gmail.com>");
-MODULE_DESCRIPTION("Loongson 1 CPUFreq driver");
+MODULE_DESCRIPTION("Loongson1 CPUFreq driver");
 MODULE_LICENSE("GPL");
index 6bed119930dd3d5e6a8c4df7a0de36511d8ade96..3c7e5b741e37d2d10a2b0ed528bcce6e09183d96 100644 (file)
@@ -9,3 +9,14 @@ config BCM47XX_NVRAM
          This driver provides an easy way to get value of requested parameter.
          It simply reads content of NVRAM and parses it. It doesn't control any
          hardware part itself.
+
+config BCM47XX_SPROM
+       bool "Broadcom SPROM driver"
+       depends on BCM47XX_NVRAM
+       help
+         Broadcom devices store configuration data in SPROM. Accessing it is
+         specific to the bus host type, e.g. PCI(e) devices have it mapped in
+         a PCI BAR.
+         In case of SoC devices SPROM content is stored on a flash used by
+         bootloader firmware CFE. This driver provides method to ssb and bcma
+         drivers to read SPROM on SoC.
index d0e683583cd6e9835ac5e2e702d8f424476b7167..f93efc479b8bfb910cd745aab6821172574d7f7f 100644 (file)
@@ -1 +1,2 @@
 obj-$(CONFIG_BCM47XX_NVRAM)            += bcm47xx_nvram.o
+obj-$(CONFIG_BCM47XX_SPROM)            += bcm47xx_sprom.o
similarity index 98%
rename from arch/mips/bcm47xx/sprom.c
rename to drivers/firmware/broadcom/bcm47xx_sprom.c
index ca7ad131d05703003ac007a6e76e8b8a358115db..b6eb875d4af39fae592704923f6e9867c45845c9 100644 (file)
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <bcm47xx.h>
-#include <linux/if_ether.h>
+#include <linux/bcm47xx_nvram.h>
+#include <linux/bcma/bcma.h>
 #include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/ssb/ssb.h>
 
 static void create_key(const char *prefix, const char *postfix,
                       const char *name, char *buf, int len)
@@ -599,7 +601,7 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
        bcm47xx_sprom_fill_auto(sprom, prefix, fallback);
 }
 
-#if defined(CONFIG_BCM47XX_SSB)
+#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM)
 static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
 {
        char prefix[10];
@@ -622,7 +624,7 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
 }
 #endif
 
-#if defined(CONFIG_BCM47XX_BCMA)
+#if IS_BUILTIN(CONFIG_BCMA)
 /*
  * Having many NVRAM entries for PCI devices led to repeating prefixes like
  * pci/1/1/ all the time and wasting flash space. So at some point Broadcom
@@ -706,19 +708,30 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
 }
 #endif
 
+static unsigned int bcm47xx_sprom_registered;
+
 /*
  * On bcm47xx we need to register SPROM fallback handler very early, so we can't
  * use anything like platform device / driver for this.
  */
-void bcm47xx_sprom_register_fallbacks(void)
+int bcm47xx_sprom_register_fallbacks(void)
 {
-#if defined(CONFIG_BCM47XX_SSB)
+       if (bcm47xx_sprom_registered)
+               return 0;
+
+#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM)
        if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb))
                pr_warn("Failed to register ssb SPROM handler\n");
 #endif
 
-#if defined(CONFIG_BCM47XX_BCMA)
+#if IS_BUILTIN(CONFIG_BCMA)
        if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma))
                pr_warn("Failed to register bcma SPROM handler\n");
 #endif
+
+       bcm47xx_sprom_registered = 1;
+
+       return 0;
 }
+
+fs_initcall(bcm47xx_sprom_register_fallbacks);
index 4dffccf532a2173ce17f289aeeb0f69bdfac4dc3..c089f49b63fb233c1156eaccdbff1d387a7e3dd1 100644 (file)
@@ -197,7 +197,7 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
 
        local_irq_save(flags);
 
-       gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+       gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), mips_cm_vp_id(cpu));
 
        if (mips_cm_is64) {
                gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE), cnt);
@@ -246,6 +246,14 @@ void gic_stop_count(void)
 
 #endif
 
+unsigned gic_read_local_vp_id(void)
+{
+       unsigned long ident;
+
+       ident = gic_read(GIC_REG(VPE_LOCAL, GIC_VP_IDENT));
+       return ident & GIC_VP_IDENT_VCNUM_MSK;
+}
+
 static bool gic_local_irq_is_routable(int intr)
 {
        u32 vpe_ctl;
@@ -553,7 +561,8 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
 
        spin_lock_irqsave(&gic_lock, flags);
        for (i = 0; i < gic_vpes; i++) {
-               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR),
+                         mips_cm_vp_id(i));
                gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
        }
        spin_unlock_irqrestore(&gic_lock, flags);
@@ -567,7 +576,8 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
 
        spin_lock_irqsave(&gic_lock, flags);
        for (i = 0; i < gic_vpes; i++) {
-               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR),
+                         mips_cm_vp_id(i));
                gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
        }
        spin_unlock_irqrestore(&gic_lock, flags);
@@ -607,7 +617,8 @@ static void __init gic_basic_init(void)
        for (i = 0; i < gic_vpes; i++) {
                unsigned int j;
 
-               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR),
+                         mips_cm_vp_id(i));
                for (j = 0; j < GIC_NUM_LOCAL_INTRS; j++) {
                        if (!gic_local_irq_is_routable(j))
                                continue;
@@ -652,7 +663,8 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
        for (i = 0; i < gic_vpes; i++) {
                u32 val = GIC_MAP_TO_PIN_MSK | gic_cpu_pin;
 
-               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+               gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR),
+                         mips_cm_vp_id(i));
 
                switch (intr) {
                case GIC_LOCAL_INT_WD:
index 125e569017be6348dd49c522791f0277067f8f1d..b3ae30a4c67b6fc04caa68b52fc307bbfb45695a 100644 (file)
@@ -15,10 +15,6 @@ menuconfig MIPS_PLATFORM_DEVICES
 
 if MIPS_PLATFORM_DEVICES
 
-config MIPS_ACPI
-       bool
-       default y if LOONGSON_MACH3X
-
 config CPU_HWMON
        tristate "Loongson CPU HWMon Driver"
        depends on LOONGSON_MACH3X
index 43412849b195deaf5e40f69d642c0fbfbd8e126f..8dfd03924c3701e5d36a164740a6da57fdc9e3cf 100644 (file)
@@ -1,2 +1 @@
-obj-$(CONFIG_MIPS_ACPI) += acpi_init.o
 obj-$(CONFIG_CPU_HWMON) += cpu_hwmon.o
index 4993e19f153182d293a65ff6fdf94a406cef3d47..4300a558d0f39a4d15e7743368bc2a3a68e98b8e 100644 (file)
@@ -20,9 +20,9 @@ int loongson3_cpu_temp(int cpu)
        u32 reg;
 
        reg = LOONGSON_CHIPTEMP(cpu);
-       if (loongson_sysconf.cputype == Loongson_3A)
+       if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1)
                reg = (reg >> 8) & 0xff;
-       else if (loongson_sysconf.cputype == Loongson_3B)
+       else
                reg = ((reg >> 8) & 0xff) - 100;
 
        return (int)reg * 1000;
index 13d4ed6caac4a78b5649cc05420b92f12eea2ee1..7711b260dacf805ebb1166ef82b4c9147036aa19 100644 (file)
@@ -900,6 +900,27 @@ config SERIAL_SGI_L1_CONSOLE
                controller serial port as your console (you want this!),
                say Y.  Otherwise, say N.
 
+config SERIAL_PIC32
+       tristate "Microchip PIC32 serial support"
+       depends on MACH_PIC32
+       select SERIAL_CORE
+       help
+         If you have a PIC32, this driver supports the serial ports.
+
+         Say Y or M to use PIC32 serial ports, otherwise say N. Note that
+         to use a serial port as a console, this must be included in kernel and
+         not as a module.
+
+config SERIAL_PIC32_CONSOLE
+       bool "PIC32 serial console support"
+       depends on SERIAL_PIC32
+       select SERIAL_CORE_CONSOLE
+       help
+         If you have a PIC32, this driver supports the putting a console on one
+         of the serial ports.
+
+         Say Y to use the PIC32 console, otherwise say N.
+
 config SERIAL_MPC52xx
        tristate "Freescale MPC52xx/MPC512x family PSC serial support"
        depends on PPC_MPC52xx || PPC_MPC512x
index 8c261adac04ea1e6d2677c07163d12d2a867b13f..74914aafac61950b7744348bd2a4c1e6c61908df 100644 (file)
@@ -91,6 +91,7 @@ obj-$(CONFIG_SERIAL_MEN_Z135) += men_z135_uart.o
 obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
 obj-$(CONFIG_SERIAL_STM32)     += stm32-usart.o
 obj-$(CONFIG_SERIAL_MVEBU_UART)        += mvebu-uart.o
+obj-$(CONFIG_SERIAL_PIC32)     += pic32_uart.o
 
 # GPIOLIB helpers for modem control lines
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)        += serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c
new file mode 100644 (file)
index 0000000..62a43bf
--- /dev/null
@@ -0,0 +1,960 @@
+/*
+ * PIC32 Integrated Serial Driver.
+ *
+ * Copyright (C) 2015 Microchip Technology, Inc.
+ *
+ * Authors:
+ *   Sorin-Andrei Pistirica <andrei.pistirica@microchip.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <linux/clk.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/delay.h>
+
+#include <asm/mach-pic32/pic32.h>
+#include "pic32_uart.h"
+
+/* UART name and device definitions */
+#define PIC32_DEV_NAME         "pic32-uart"
+#define PIC32_MAX_UARTS                6
+#define PIC32_SDEV_NAME                "ttyPIC"
+
+/* pic32_sport pointer for console use */
+static struct pic32_sport *pic32_sports[PIC32_MAX_UARTS];
+
+static inline void pic32_wait_deplete_txbuf(struct pic32_sport *sport)
+{
+       /* wait for tx empty, otherwise chars will be lost or corrupted */
+       while (!(pic32_uart_readl(sport, PIC32_UART_STA) & PIC32_UART_STA_TRMT))
+               udelay(1);
+}
+
+static inline int pic32_enable_clock(struct pic32_sport *sport)
+{
+       int ret = clk_prepare_enable(sport->clk);
+
+       if (ret)
+               return ret;
+
+       sport->ref_clk++;
+       return 0;
+}
+
+static inline void pic32_disable_clock(struct pic32_sport *sport)
+{
+       sport->ref_clk--;
+       clk_disable_unprepare(sport->clk);
+}
+
+/* serial core request to check if uart tx buffer is empty */
+static unsigned int pic32_uart_tx_empty(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       u32 val = pic32_uart_readl(sport, PIC32_UART_STA);
+
+       return (val & PIC32_UART_STA_TRMT) ? 1 : 0;
+}
+
+/* serial core request to set UART outputs */
+static void pic32_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       /* set loopback mode */
+       if (mctrl & TIOCM_LOOP)
+               pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_LPBK);
+       else
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_LPBK);
+}
+
+/* get the state of CTS input pin for this port */
+static unsigned int get_cts_state(struct pic32_sport *sport)
+{
+       /* read and invert UxCTS */
+       if (gpio_is_valid(sport->cts_gpio))
+               return !gpio_get_value(sport->cts_gpio);
+
+       return 1;
+}
+
+/* serial core request to return the state of misc UART input pins */
+static unsigned int pic32_uart_get_mctrl(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       unsigned int mctrl = 0;
+
+       if (!sport->hw_flow_ctrl)
+               mctrl |= TIOCM_CTS;
+       else if (get_cts_state(sport))
+               mctrl |= TIOCM_CTS;
+
+       /* DSR and CD are not supported in PIC32, so return 1
+        * RI is not supported in PIC32, so return 0
+        */
+       mctrl |= TIOCM_CD;
+       mctrl |= TIOCM_DSR;
+
+       return mctrl;
+}
+
+/* stop tx and start tx are not called in pairs, therefore a flag indicates
+ * the status of irq to control the irq-depth.
+ */
+static inline void pic32_uart_irqtxen(struct pic32_sport *sport, u8 en)
+{
+       if (en && !tx_irq_enabled(sport)) {
+               enable_irq(sport->irq_tx);
+               tx_irq_enabled(sport) = 1;
+       } else if (!en && tx_irq_enabled(sport)) {
+               /* use disable_irq_nosync() and not disable_irq() to avoid self
+                * imposed deadlock by not waiting for irq handler to end,
+                * since this callback is called from interrupt context.
+                */
+               disable_irq_nosync(sport->irq_tx);
+               tx_irq_enabled(sport) = 0;
+       }
+}
+
+/* serial core request to disable tx ASAP (used for flow control) */
+static void pic32_uart_stop_tx(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       if (!(pic32_uart_readl(sport, PIC32_UART_MODE) & PIC32_UART_MODE_ON))
+               return;
+
+       if (!(pic32_uart_readl(sport, PIC32_UART_STA) & PIC32_UART_STA_UTXEN))
+               return;
+
+       /* wait for tx empty */
+       pic32_wait_deplete_txbuf(sport);
+
+       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+                               PIC32_UART_STA_UTXEN);
+       pic32_uart_irqtxen(sport, 0);
+}
+
+/* serial core request to (re)enable tx */
+static void pic32_uart_start_tx(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       pic32_uart_irqtxen(sport, 1);
+       pic32_uart_writel(sport, PIC32_SET(PIC32_UART_STA),
+                               PIC32_UART_STA_UTXEN);
+}
+
+/* serial core request to stop rx, called before port shutdown */
+static void pic32_uart_stop_rx(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       /* disable rx interrupts */
+       disable_irq(sport->irq_rx);
+
+       /* receiver Enable bit OFF */
+       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+                               PIC32_UART_STA_URXEN);
+}
+
+/* serial core request to start/stop emitting break char */
+static void pic32_uart_break_ctl(struct uart_port *port, int ctl)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       if (ctl)
+               pic32_uart_writel(sport, PIC32_SET(PIC32_UART_STA),
+                                       PIC32_UART_STA_UTXBRK);
+       else
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+                                       PIC32_UART_STA_UTXBRK);
+
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* get port type in string format */
+static const char *pic32_uart_type(struct uart_port *port)
+{
+       return (port->type == PORT_PIC32) ? PIC32_DEV_NAME : NULL;
+}
+
+/* read all chars in rx fifo and send them to core */
+static void pic32_uart_do_rx(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       struct tty_port *tty;
+       unsigned int max_count;
+
+       /* limit number of char read in interrupt, should not be
+        * higher than fifo size anyway since we're much faster than
+        * serial port
+        */
+       max_count = PIC32_UART_RX_FIFO_DEPTH;
+
+       spin_lock(&port->lock);
+
+       tty = &port->state->port;
+
+       do {
+               u32 sta_reg, c;
+               char flag;
+
+               /* get overrun/fifo empty information from status register */
+               sta_reg = pic32_uart_readl(sport, PIC32_UART_STA);
+               if (unlikely(sta_reg & PIC32_UART_STA_OERR)) {
+
+                       /* fifo reset is required to clear interrupt */
+                       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+                                               PIC32_UART_STA_OERR);
+
+                       port->icount.overrun++;
+                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+               }
+
+               /* Can at least one more character can be read? */
+               if (!(sta_reg & PIC32_UART_STA_URXDA))
+                       break;
+
+               /* read the character and increment the rx counter */
+               c = pic32_uart_readl(sport, PIC32_UART_RX);
+
+               port->icount.rx++;
+               flag = TTY_NORMAL;
+               c &= 0xff;
+
+               if (unlikely((sta_reg & PIC32_UART_STA_PERR) ||
+                            (sta_reg & PIC32_UART_STA_FERR))) {
+
+                       /* do stats first */
+                       if (sta_reg & PIC32_UART_STA_PERR)
+                               port->icount.parity++;
+                       if (sta_reg & PIC32_UART_STA_FERR)
+                               port->icount.frame++;
+
+                       /* update flag wrt read_status_mask */
+                       sta_reg &= port->read_status_mask;
+
+                       if (sta_reg & PIC32_UART_STA_FERR)
+                               flag = TTY_FRAME;
+                       if (sta_reg & PIC32_UART_STA_PERR)
+                               flag = TTY_PARITY;
+               }
+
+               if (uart_handle_sysrq_char(port, c))
+                       continue;
+
+               if ((sta_reg & port->ignore_status_mask) == 0)
+                       tty_insert_flip_char(tty, c, flag);
+
+       } while (--max_count);
+
+       spin_unlock(&port->lock);
+
+       tty_flip_buffer_push(tty);
+}
+
+/* fill tx fifo with chars to send, stop when fifo is about to be full
+ * or when all chars have been sent.
+ */
+static void pic32_uart_do_tx(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       struct circ_buf *xmit = &port->state->xmit;
+       unsigned int max_count = PIC32_UART_TX_FIFO_DEPTH;
+
+       if (port->x_char) {
+               pic32_uart_writel(sport, PIC32_UART_TX, port->x_char);
+               port->icount.tx++;
+               port->x_char = 0;
+               return;
+       }
+
+       if (uart_tx_stopped(port)) {
+               pic32_uart_stop_tx(port);
+               return;
+       }
+
+       if (uart_circ_empty(xmit))
+               goto txq_empty;
+
+       /* keep stuffing chars into uart tx buffer
+        * 1) until uart fifo is full
+        * or
+        * 2) until the circ buffer is empty
+        * (all chars have been sent)
+        * or
+        * 3) until the max count is reached
+        * (prevents lingering here for too long in certain cases)
+        */
+       while (!(PIC32_UART_STA_UTXBF &
+               pic32_uart_readl(sport, PIC32_UART_STA))) {
+               unsigned int c = xmit->buf[xmit->tail];
+
+               pic32_uart_writel(sport, PIC32_UART_TX, c);
+
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               port->icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+               if (--max_count == 0)
+                       break;
+       }
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+
+       if (uart_circ_empty(xmit))
+               goto txq_empty;
+
+       return;
+
+txq_empty:
+       pic32_uart_irqtxen(sport, 0);
+}
+
+/* RX interrupt handler */
+static irqreturn_t pic32_uart_rx_interrupt(int irq, void *dev_id)
+{
+       struct uart_port *port = dev_id;
+
+       pic32_uart_do_rx(port);
+
+       return IRQ_HANDLED;
+}
+
+/* TX interrupt handler */
+static irqreturn_t pic32_uart_tx_interrupt(int irq, void *dev_id)
+{
+       struct uart_port *port = dev_id;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       pic32_uart_do_tx(port);
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+/* FAULT interrupt handler */
+static irqreturn_t pic32_uart_fault_interrupt(int irq, void *dev_id)
+{
+       /* do nothing: pic32_uart_do_rx() handles faults. */
+       return IRQ_HANDLED;
+}
+
+/* enable rx & tx operation on uart */
+static void pic32_uart_en_and_unmask(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       pic32_uart_writel(sport, PIC32_SET(PIC32_UART_STA),
+                               PIC32_UART_STA_UTXEN | PIC32_UART_STA_URXEN);
+       pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
+                               PIC32_UART_MODE_ON);
+}
+
+/* disable rx & tx operation on uart */
+static void pic32_uart_dsbl_and_mask(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       /* wait for tx empty, otherwise chars will be lost or corrupted */
+       pic32_wait_deplete_txbuf(sport);
+
+       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+                               PIC32_UART_STA_UTXEN | PIC32_UART_STA_URXEN);
+       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                               PIC32_UART_MODE_ON);
+}
+
+/* serial core request to initialize uart and start rx operation */
+static int pic32_uart_startup(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       u32 dflt_baud = (port->uartclk / PIC32_UART_DFLT_BRATE / 16) - 1;
+       unsigned long flags;
+       int ret;
+
+       local_irq_save(flags);
+
+       ret = pic32_enable_clock(sport);
+       if (ret) {
+               local_irq_restore(flags);
+               goto out_done;
+       }
+
+       /* clear status and mode registers */
+       pic32_uart_writel(sport, PIC32_UART_MODE, 0);
+       pic32_uart_writel(sport, PIC32_UART_STA, 0);
+
+       /* disable uart and mask all interrupts */
+       pic32_uart_dsbl_and_mask(port);
+
+       /* set default baud */
+       pic32_uart_writel(sport, PIC32_UART_BRG, dflt_baud);
+
+       local_irq_restore(flags);
+
+       /* Each UART of a PIC32 has three interrupts therefore,
+        * we setup driver to register the 3 irqs for the device.
+        *
+        * For each irq request_irq() is called with interrupt disabled.
+        * And the irq is enabled as soon as we are ready to handle them.
+        */
+       tx_irq_enabled(sport) = 0;
+
+       sport->irq_fault_name = kasprintf(GFP_KERNEL, "%s%d-fault",
+                                         pic32_uart_type(port),
+                                         sport->idx);
+       if (!sport->irq_fault_name) {
+               dev_err(port->dev, "%s: kasprintf err!", __func__);
+               ret = -ENOMEM;
+               goto out_done;
+       }
+       irq_set_status_flags(sport->irq_fault, IRQ_NOAUTOEN);
+       ret = request_irq(sport->irq_fault, pic32_uart_fault_interrupt,
+                         sport->irqflags_fault, sport->irq_fault_name, port);
+       if (ret) {
+               dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
+                       __func__, sport->irq_fault, ret,
+                       pic32_uart_type(port));
+               goto out_f;
+       }
+
+       sport->irq_rx_name = kasprintf(GFP_KERNEL, "%s%d-rx",
+                                      pic32_uart_type(port),
+                                      sport->idx);
+       if (!sport->irq_rx_name) {
+               dev_err(port->dev, "%s: kasprintf err!", __func__);
+               kfree(sport->irq_fault_name);
+               ret = -ENOMEM;
+               goto out_f;
+       }
+       irq_set_status_flags(sport->irq_rx, IRQ_NOAUTOEN);
+       ret = request_irq(sport->irq_rx, pic32_uart_rx_interrupt,
+                         sport->irqflags_rx, sport->irq_rx_name, port);
+       if (ret) {
+               dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
+                       __func__, sport->irq_rx, ret,
+                       pic32_uart_type(port));
+               goto out_r;
+       }
+
+       sport->irq_tx_name = kasprintf(GFP_KERNEL, "%s%d-tx",
+                                      pic32_uart_type(port),
+                                      sport->idx);
+       if (!sport->irq_tx_name) {
+               dev_err(port->dev, "%s: kasprintf err!", __func__);
+               ret = -ENOMEM;
+               goto out_r;
+       }
+       irq_set_status_flags(sport->irq_tx, IRQ_NOAUTOEN);
+       ret = request_irq(sport->irq_tx, pic32_uart_tx_interrupt,
+                         sport->irqflags_tx, sport->irq_tx_name, port);
+       if (ret) {
+               dev_err(port->dev, "%s: request irq(%d) err! ret:%d name:%s\n",
+                       __func__, sport->irq_tx, ret,
+                       pic32_uart_type(port));
+               goto out_t;
+       }
+
+       local_irq_save(flags);
+
+       /* set rx interrupt on first receive */
+       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+                       PIC32_UART_STA_URXISEL1 | PIC32_UART_STA_URXISEL0);
+
+       /* set interrupt on empty */
+       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+                       PIC32_UART_STA_UTXISEL1);
+
+       /* enable all interrupts and eanable uart */
+       pic32_uart_en_and_unmask(port);
+
+       enable_irq(sport->irq_rx);
+
+       return 0;
+
+out_t:
+       kfree(sport->irq_tx_name);
+       free_irq(sport->irq_tx, sport);
+out_r:
+       kfree(sport->irq_rx_name);
+       free_irq(sport->irq_rx, sport);
+out_f:
+       kfree(sport->irq_fault_name);
+       free_irq(sport->irq_fault, sport);
+out_done:
+       return ret;
+}
+
+/* serial core request to flush & disable uart */
+static void pic32_uart_shutdown(struct uart_port *port)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       unsigned long flags;
+
+       /* disable uart */
+       spin_lock_irqsave(&port->lock, flags);
+       pic32_uart_dsbl_and_mask(port);
+       spin_unlock_irqrestore(&port->lock, flags);
+       pic32_disable_clock(sport);
+
+       /* free all 3 interrupts for this UART */
+       free_irq(sport->irq_fault, port);
+       free_irq(sport->irq_tx, port);
+       free_irq(sport->irq_rx, port);
+}
+
+/* serial core request to change current uart setting */
+static void pic32_uart_set_termios(struct uart_port *port,
+                                  struct ktermios *new,
+                                  struct ktermios *old)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+       unsigned int baud;
+       unsigned int quot;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       /* disable uart and mask all interrupts while changing speed */
+       pic32_uart_dsbl_and_mask(port);
+
+       /* stop bit options */
+       if (new->c_cflag & CSTOPB)
+               pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_STSEL);
+       else
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_STSEL);
+
+       /* parity options */
+       if (new->c_cflag & PARENB) {
+               if (new->c_cflag & PARODD) {
+                       pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_PDSEL1);
+                       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_PDSEL0);
+               } else {
+                       pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_PDSEL0);
+                       pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_PDSEL1);
+               }
+       } else {
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_PDSEL1 |
+                                       PIC32_UART_MODE_PDSEL0);
+       }
+       /* if hw flow ctrl, then the pins must be specified in device tree */
+       if ((new->c_cflag & CRTSCTS) && sport->hw_flow_ctrl) {
+               /* enable hardware flow control */
+               pic32_uart_writel(sport, PIC32_SET(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_UEN1);
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_UEN0);
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_RTSMD);
+       } else {
+               /* disable hardware flow control */
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_UEN1);
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_UEN0);
+               pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_MODE),
+                                       PIC32_UART_MODE_RTSMD);
+       }
+
+       /* Always 8-bit */
+       new->c_cflag |= CS8;
+
+       /* Mark/Space parity is not supported */
+       new->c_cflag &= ~CMSPAR;
+
+       /* update baud */
+       baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
+       quot = uart_get_divisor(port, baud) - 1;
+       pic32_uart_writel(sport, PIC32_UART_BRG, quot);
+       uart_update_timeout(port, new->c_cflag, baud);
+
+       if (tty_termios_baud_rate(new))
+               tty_termios_encode_baud_rate(new, baud, baud);
+
+       /* enable uart */
+       pic32_uart_en_and_unmask(port);
+
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/* serial core request to claim uart iomem */
+static int pic32_uart_request_port(struct uart_port *port)
+{
+       struct platform_device *pdev = to_platform_device(port->dev);
+       struct resource *res_mem;
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(!res_mem))
+               return -EINVAL;
+
+       if (!request_mem_region(port->mapbase, resource_size(res_mem),
+                               "pic32_uart_mem"))
+               return -EBUSY;
+
+       port->membase = devm_ioremap_nocache(port->dev, port->mapbase,
+                                               resource_size(res_mem));
+       if (!port->membase) {
+               dev_err(port->dev, "Unable to map registers\n");
+               release_mem_region(port->mapbase, resource_size(res_mem));
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/* serial core request to release uart iomem */
+static void pic32_uart_release_port(struct uart_port *port)
+{
+       struct platform_device *pdev = to_platform_device(port->dev);
+       struct resource *res_mem;
+       unsigned int res_size;
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(!res_mem))
+               return;
+       res_size = resource_size(res_mem);
+
+       release_mem_region(port->mapbase, res_size);
+}
+
+/* serial core request to do any port required auto-configuration */
+static void pic32_uart_config_port(struct uart_port *port, int flags)
+{
+       if (flags & UART_CONFIG_TYPE) {
+               if (pic32_uart_request_port(port))
+                       return;
+               port->type = PORT_PIC32;
+       }
+}
+
+/* serial core request to check that port information in serinfo are suitable */
+static int pic32_uart_verify_port(struct uart_port *port,
+                                 struct serial_struct *serinfo)
+{
+       if (port->type != PORT_PIC32)
+               return -EINVAL;
+       if (port->irq != serinfo->irq)
+               return -EINVAL;
+       if (port->iotype != serinfo->io_type)
+               return -EINVAL;
+       if (port->mapbase != (unsigned long)serinfo->iomem_base)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* serial core callbacks */
+static const struct uart_ops pic32_uart_ops = {
+       .tx_empty       = pic32_uart_tx_empty,
+       .get_mctrl      = pic32_uart_get_mctrl,
+       .set_mctrl      = pic32_uart_set_mctrl,
+       .start_tx       = pic32_uart_start_tx,
+       .stop_tx        = pic32_uart_stop_tx,
+       .stop_rx        = pic32_uart_stop_rx,
+       .break_ctl      = pic32_uart_break_ctl,
+       .startup        = pic32_uart_startup,
+       .shutdown       = pic32_uart_shutdown,
+       .set_termios    = pic32_uart_set_termios,
+       .type           = pic32_uart_type,
+       .release_port   = pic32_uart_release_port,
+       .request_port   = pic32_uart_request_port,
+       .config_port    = pic32_uart_config_port,
+       .verify_port    = pic32_uart_verify_port,
+};
+
+#ifdef CONFIG_SERIAL_PIC32_CONSOLE
+/* output given char */
+static void pic32_console_putchar(struct uart_port *port, int ch)
+{
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       if (!(pic32_uart_readl(sport, PIC32_UART_MODE) & PIC32_UART_MODE_ON))
+               return;
+
+       if (!(pic32_uart_readl(sport, PIC32_UART_STA) & PIC32_UART_STA_UTXEN))
+               return;
+
+       /* wait for tx empty */
+       pic32_wait_deplete_txbuf(sport);
+
+       pic32_uart_writel(sport, PIC32_UART_TX, ch & 0xff);
+}
+
+/* console core request to output given string */
+static void pic32_console_write(struct console *co, const char *s,
+                               unsigned int count)
+{
+       struct pic32_sport *sport = pic32_sports[co->index];
+       struct uart_port *port = pic32_get_port(sport);
+
+       /* call uart helper to deal with \r\n */
+       uart_console_write(port, s, count, pic32_console_putchar);
+}
+
+/* console core request to setup given console, find matching uart
+ * port and setup it.
+ */
+static int pic32_console_setup(struct console *co, char *options)
+{
+       struct pic32_sport *sport;
+       struct uart_port *port = NULL;
+       int baud = 115200;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+       int ret = 0;
+
+       if (unlikely(co->index < 0 || co->index >= PIC32_MAX_UARTS))
+               return -ENODEV;
+
+       sport = pic32_sports[co->index];
+       if (!sport)
+               return -ENODEV;
+       port = pic32_get_port(sport);
+
+       ret = pic32_enable_clock(sport);
+       if (ret)
+               return ret;
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver pic32_uart_driver;
+static struct console pic32_console = {
+       .name           = PIC32_SDEV_NAME,
+       .write          = pic32_console_write,
+       .device         = uart_console_device,
+       .setup          = pic32_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+       .data           = &pic32_uart_driver,
+};
+#define PIC32_SCONSOLE (&pic32_console)
+
+static int __init pic32_console_init(void)
+{
+       register_console(&pic32_console);
+       return 0;
+}
+console_initcall(pic32_console_init);
+
+static inline bool is_pic32_console_port(struct uart_port *port)
+{
+       return port->cons && port->cons->index == port->line;
+}
+
+/*
+ * Late console initialization.
+ */
+static int __init pic32_late_console_init(void)
+{
+       if (!(pic32_console.flags & CON_ENABLED))
+               register_console(&pic32_console);
+
+       return 0;
+}
+
+core_initcall(pic32_late_console_init);
+
+#else
+#define PIC32_SCONSOLE NULL
+#endif
+
+static struct uart_driver pic32_uart_driver = {
+       .owner                  = THIS_MODULE,
+       .driver_name            = PIC32_DEV_NAME,
+       .dev_name               = PIC32_SDEV_NAME,
+       .nr                     = PIC32_MAX_UARTS,
+       .cons                   = PIC32_SCONSOLE,
+};
+
+static int pic32_uart_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct pic32_sport *sport;
+       int uart_idx = 0;
+       struct resource *res_mem;
+       struct uart_port *port;
+       int ret;
+
+       uart_idx = of_alias_get_id(np, "serial");
+       if (uart_idx < 0 || uart_idx >= PIC32_MAX_UARTS)
+               return -EINVAL;
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res_mem)
+               return -EINVAL;
+
+       sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
+       if (!sport)
+               return -ENOMEM;
+
+       sport->idx              = uart_idx;
+       sport->irq_fault        = irq_of_parse_and_map(np, 0);
+       sport->irqflags_fault   = IRQF_NO_THREAD;
+       sport->irq_rx           = irq_of_parse_and_map(np, 1);
+       sport->irqflags_rx      = IRQF_NO_THREAD;
+       sport->irq_tx           = irq_of_parse_and_map(np, 2);
+       sport->irqflags_tx      = IRQF_NO_THREAD;
+       sport->clk              = devm_clk_get(&pdev->dev, NULL);
+       sport->cts_gpio         = -EINVAL;
+       sport->dev              = &pdev->dev;
+
+       /* Hardware flow control: gpios
+        * !Note: Basically, CTS is needed for reading the status.
+        */
+       sport->hw_flow_ctrl = false;
+       sport->cts_gpio = of_get_named_gpio(np, "cts-gpios", 0);
+       if (gpio_is_valid(sport->cts_gpio)) {
+               sport->hw_flow_ctrl = true;
+
+               ret = devm_gpio_request(sport->dev,
+                                       sport->cts_gpio, "CTS");
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "error requesting CTS GPIO\n");
+                       goto err;
+               }
+
+               ret = gpio_direction_input(sport->cts_gpio);
+               if (ret) {
+                       dev_err(&pdev->dev, "error setting CTS GPIO\n");
+                       goto err;
+               }
+       }
+
+       pic32_sports[uart_idx] = sport;
+       port = &sport->port;
+       memset(port, 0, sizeof(*port));
+       port->iotype    = UPIO_MEM;
+       port->mapbase   = res_mem->start;
+       port->ops       = &pic32_uart_ops;
+       port->flags     = UPF_BOOT_AUTOCONF;
+       port->dev       = &pdev->dev;
+       port->fifosize  = PIC32_UART_TX_FIFO_DEPTH;
+       port->uartclk   = clk_get_rate(sport->clk);
+       port->line      = uart_idx;
+
+       ret = uart_add_one_port(&pic32_uart_driver, port);
+       if (ret) {
+               port->membase = NULL;
+               dev_err(port->dev, "%s: uart add port error!\n", __func__);
+               goto err;
+       }
+
+#ifdef CONFIG_SERIAL_PIC32_CONSOLE
+       if (is_pic32_console_port(port) &&
+           (pic32_console.flags & CON_ENABLED)) {
+               /* The peripheral clock has been enabled by console_setup,
+                * so disable it till the port is used.
+                */
+               pic32_disable_clock(sport);
+       }
+#endif
+
+       platform_set_drvdata(pdev, port);
+
+       dev_info(&pdev->dev, "%s: uart(%d) driver initialized.\n",
+                __func__, uart_idx);
+
+       return 0;
+err:
+       /* automatic unroll of sport and gpios */
+       return ret;
+}
+
+static int pic32_uart_remove(struct platform_device *pdev)
+{
+       struct uart_port *port = platform_get_drvdata(pdev);
+       struct pic32_sport *sport = to_pic32_sport(port);
+
+       uart_remove_one_port(&pic32_uart_driver, port);
+       pic32_disable_clock(sport);
+       platform_set_drvdata(pdev, NULL);
+       pic32_sports[sport->idx] = NULL;
+
+       /* automatic unroll of sport and gpios */
+       return 0;
+}
+
+static const struct of_device_id pic32_serial_dt_ids[] = {
+       { .compatible = "microchip,pic32mzda-uart" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pic32_serial_dt_ids);
+
+static struct platform_driver pic32_uart_platform_driver = {
+       .probe          = pic32_uart_probe,
+       .remove         = pic32_uart_remove,
+       .driver         = {
+               .name   = PIC32_DEV_NAME,
+               .of_match_table = of_match_ptr(pic32_serial_dt_ids),
+       },
+};
+
+static int __init pic32_uart_init(void)
+{
+       int ret;
+
+       ret = uart_register_driver(&pic32_uart_driver);
+       if (ret) {
+               pr_err("failed to register %s:%d\n",
+                      pic32_uart_driver.driver_name, ret);
+               return ret;
+       }
+
+       ret = platform_driver_register(&pic32_uart_platform_driver);
+       if (ret) {
+               pr_err("fail to register pic32 uart\n");
+               uart_unregister_driver(&pic32_uart_driver);
+       }
+
+       return ret;
+}
+arch_initcall(pic32_uart_init);
+
+static void __exit pic32_uart_exit(void)
+{
+#ifdef CONFIG_SERIAL_PIC32_CONSOLE
+       unregister_console(&pic32_console);
+#endif
+       platform_driver_unregister(&pic32_uart_platform_driver);
+       uart_unregister_driver(&pic32_uart_driver);
+}
+module_exit(pic32_uart_exit);
+
+MODULE_AUTHOR("Sorin-Andrei Pistirica <andrei.pistirica@microchip.com>");
+MODULE_DESCRIPTION("Microchip PIC32 integrated serial port driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/pic32_uart.h b/drivers/tty/serial/pic32_uart.h
new file mode 100644 (file)
index 0000000..ec379da
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * PIC32 Integrated Serial Driver.
+ *
+ * Copyright (C) 2015 Microchip Technology, Inc.
+ *
+ * Authors:
+ *   Sorin-Andrei Pistirica <andrei.pistirica@microchip.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#ifndef __DT_PIC32_UART_H__
+#define __DT_PIC32_UART_H__
+
+#define PIC32_UART_DFLT_BRATE          (9600)
+#define PIC32_UART_TX_FIFO_DEPTH       (8)
+#define PIC32_UART_RX_FIFO_DEPTH       (8)
+
+#define PIC32_UART_MODE                0x00
+#define PIC32_UART_STA         0x10
+#define PIC32_UART_TX          0x20
+#define PIC32_UART_RX          0x30
+#define PIC32_UART_BRG         0x40
+
+struct pic32_console_opt {
+       int baud;
+       int parity;
+       int bits;
+       int flow;
+};
+
+/* struct pic32_sport - pic32 serial port descriptor
+ * @port: uart port descriptor
+ * @idx: port index
+ * @irq_fault: virtual fault interrupt number
+ * @irqflags_fault: flags related to fault irq
+ * @irq_fault_name: irq fault name
+ * @irq_rx: virtual rx interrupt number
+ * @irqflags_rx: flags related to rx irq
+ * @irq_rx_name: irq rx name
+ * @irq_tx: virtual tx interrupt number
+ * @irqflags_tx: : flags related to tx irq
+ * @irq_tx_name: irq tx name
+ * @cts_gpio: clear to send gpio
+ * @dev: device descriptor
+ **/
+struct pic32_sport {
+       struct uart_port port;
+       struct pic32_console_opt opt;
+       int idx;
+
+       int irq_fault;
+       int irqflags_fault;
+       const char *irq_fault_name;
+       int irq_rx;
+       int irqflags_rx;
+       const char *irq_rx_name;
+       int irq_tx;
+       int irqflags_tx;
+       const char *irq_tx_name;
+       u8 enable_tx_irq;
+
+       bool hw_flow_ctrl;
+       int cts_gpio;
+
+       int ref_clk;
+       struct clk *clk;
+
+       struct device *dev;
+};
+#define to_pic32_sport(c) container_of(c, struct pic32_sport, port)
+#define pic32_get_port(sport) (&sport->port)
+#define pic32_get_opt(sport) (&sport->opt)
+#define tx_irq_enabled(sport) (sport->enable_tx_irq)
+
+static inline void pic32_uart_writel(struct pic32_sport *sport,
+                                       u32 reg, u32 val)
+{
+       struct uart_port *port = pic32_get_port(sport);
+
+       __raw_writel(val, port->membase + reg);
+}
+
+static inline u32 pic32_uart_readl(struct pic32_sport *sport, u32 reg)
+{
+       struct uart_port *port = pic32_get_port(sport);
+
+       return  __raw_readl(port->membase + reg);
+}
+
+/* pic32 uart mode register bits */
+#define PIC32_UART_MODE_ON        BIT(15)
+#define PIC32_UART_MODE_FRZ       BIT(14)
+#define PIC32_UART_MODE_SIDL      BIT(13)
+#define PIC32_UART_MODE_IREN      BIT(12)
+#define PIC32_UART_MODE_RTSMD     BIT(11)
+#define PIC32_UART_MODE_RESV1     BIT(10)
+#define PIC32_UART_MODE_UEN1      BIT(9)
+#define PIC32_UART_MODE_UEN0      BIT(8)
+#define PIC32_UART_MODE_WAKE      BIT(7)
+#define PIC32_UART_MODE_LPBK      BIT(6)
+#define PIC32_UART_MODE_ABAUD     BIT(5)
+#define PIC32_UART_MODE_RXINV     BIT(4)
+#define PIC32_UART_MODE_BRGH      BIT(3)
+#define PIC32_UART_MODE_PDSEL1    BIT(2)
+#define PIC32_UART_MODE_PDSEL0    BIT(1)
+#define PIC32_UART_MODE_STSEL     BIT(0)
+
+/* pic32 uart status register bits */
+#define PIC32_UART_STA_UTXISEL1   BIT(15)
+#define PIC32_UART_STA_UTXISEL0   BIT(14)
+#define PIC32_UART_STA_UTXINV     BIT(13)
+#define PIC32_UART_STA_URXEN      BIT(12)
+#define PIC32_UART_STA_UTXBRK     BIT(11)
+#define PIC32_UART_STA_UTXEN      BIT(10)
+#define PIC32_UART_STA_UTXBF      BIT(9)
+#define PIC32_UART_STA_TRMT       BIT(8)
+#define PIC32_UART_STA_URXISEL1   BIT(7)
+#define PIC32_UART_STA_URXISEL0   BIT(6)
+#define PIC32_UART_STA_ADDEN      BIT(5)
+#define PIC32_UART_STA_RIDLE      BIT(4)
+#define PIC32_UART_STA_PERR       BIT(3)
+#define PIC32_UART_STA_FERR       BIT(2)
+#define PIC32_UART_STA_OERR       BIT(1)
+#define PIC32_UART_STA_URXDA      BIT(0)
+
+#endif /* __DT_PIC32_UART_H__ */
index 04dcedfdebf876bde5398284c17d54b73f04f4e5..0449235d4f22dd2d1b068c85243e8536b5adffa7 100644 (file)
@@ -1245,11 +1245,6 @@ MODULE_LICENSE ("GPL");
 #define TMIO_OHCI_DRIVER       ohci_hcd_tmio_driver
 #endif
 
-#ifdef CONFIG_MACH_JZ4740
-#include "ohci-jz4740.c"
-#define PLATFORM_DRIVER        ohci_hcd_jz4740_driver
-#endif
-
 #ifdef CONFIG_TILE_USB
 #include "ohci-tilegx.c"
 #define PLATFORM_DRIVER                ohci_hcd_tilegx_driver
diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
deleted file mode 100644 (file)
index 4db78f1..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under  the terms of the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-
-struct jz4740_ohci_hcd {
-       struct ohci_hcd ohci_hcd;
-
-       struct regulator *vbus;
-       bool vbus_enabled;
-       struct clk *clk;
-};
-
-static inline struct jz4740_ohci_hcd *hcd_to_jz4740_hcd(struct usb_hcd *hcd)
-{
-       return (struct jz4740_ohci_hcd *)(hcd->hcd_priv);
-}
-
-static inline struct usb_hcd *jz4740_hcd_to_hcd(struct jz4740_ohci_hcd *jz4740_ohci)
-{
-       return container_of((void *)jz4740_ohci, struct usb_hcd, hcd_priv);
-}
-
-static int ohci_jz4740_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       int     ret;
-
-       ret = ohci_init(ohci);
-       if (ret < 0)
-               return ret;
-
-       ohci->num_ports = 1;
-
-       ret = ohci_run(ohci);
-       if (ret < 0) {
-               dev_err(hcd->self.controller, "Can not start %s",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-       return 0;
-}
-
-static int ohci_jz4740_set_vbus_power(struct jz4740_ohci_hcd *jz4740_ohci,
-       bool enabled)
-{
-       int ret = 0;
-
-       if (!jz4740_ohci->vbus)
-               return 0;
-
-       if (enabled && !jz4740_ohci->vbus_enabled) {
-               ret = regulator_enable(jz4740_ohci->vbus);
-               if (ret)
-                       dev_err(jz4740_hcd_to_hcd(jz4740_ohci)->self.controller,
-                               "Could not power vbus\n");
-       } else if (!enabled && jz4740_ohci->vbus_enabled) {
-               ret = regulator_disable(jz4740_ohci->vbus);
-       }
-
-       if (ret == 0)
-               jz4740_ohci->vbus_enabled = enabled;
-
-       return ret;
-}
-
-static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
-       u16 wIndex, char *buf, u16 wLength)
-{
-       struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
-       int ret = 0;
-
-       switch (typeReq) {
-       case SetPortFeature:
-               if (wValue == USB_PORT_FEAT_POWER)
-                       ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true);
-               break;
-       case ClearPortFeature:
-               if (wValue == USB_PORT_FEAT_POWER)
-                       ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false);
-               break;
-       }
-
-       if (ret)
-               return ret;
-
-       return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
-}
-
-
-static const struct hc_driver ohci_jz4740_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "JZ4740 OHCI",
-       .hcd_priv_size =        sizeof(struct jz4740_ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_jz4740_start,
-       .stop =                 ohci_stop,
-       .shutdown =             ohci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_jz4740_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-
-static int jz4740_ohci_probe(struct platform_device *pdev)
-{
-       int ret;
-       struct usb_hcd *hcd;
-       struct jz4740_ohci_hcd *jz4740_ohci;
-       struct resource *res;
-       int irq;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "Failed to get platform irq\n");
-               return irq;
-       }
-
-       hcd = usb_create_hcd(&ohci_jz4740_hc_driver, &pdev->dev, "jz4740");
-       if (!hcd) {
-               dev_err(&pdev->dev, "Failed to create hcd.\n");
-               return -ENOMEM;
-       }
-
-       jz4740_ohci = hcd_to_jz4740_hcd(hcd);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hcd->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(hcd->regs)) {
-               ret = PTR_ERR(hcd->regs);
-               goto err_free;
-       }
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       jz4740_ohci->clk = devm_clk_get(&pdev->dev, "uhc");
-       if (IS_ERR(jz4740_ohci->clk)) {
-               ret = PTR_ERR(jz4740_ohci->clk);
-               dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
-               goto err_free;
-       }
-
-       jz4740_ohci->vbus = devm_regulator_get(&pdev->dev, "vbus");
-       if (IS_ERR(jz4740_ohci->vbus))
-               jz4740_ohci->vbus = NULL;
-
-
-       clk_set_rate(jz4740_ohci->clk, 48000000);
-       clk_enable(jz4740_ohci->clk);
-       if (jz4740_ohci->vbus)
-               ohci_jz4740_set_vbus_power(jz4740_ohci, true);
-
-       platform_set_drvdata(pdev, hcd);
-
-       ohci_hcd_init(hcd_to_ohci(hcd));
-
-       ret = usb_add_hcd(hcd, irq, 0);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret);
-               goto err_disable;
-       }
-       device_wakeup_enable(hcd->self.controller);
-
-       return 0;
-
-err_disable:
-       if (jz4740_ohci->vbus)
-               regulator_disable(jz4740_ohci->vbus);
-       clk_disable(jz4740_ohci->clk);
-
-err_free:
-       usb_put_hcd(hcd);
-
-       return ret;
-}
-
-static int jz4740_ohci_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-       struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
-
-       usb_remove_hcd(hcd);
-
-       if (jz4740_ohci->vbus)
-               regulator_disable(jz4740_ohci->vbus);
-
-       clk_disable(jz4740_ohci->clk);
-
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-static struct platform_driver ohci_hcd_jz4740_driver = {
-       .probe = jz4740_ohci_probe,
-       .remove = jz4740_ohci_remove,
-       .driver = {
-               .name = "jz4740-ohci",
-       },
-};
-
-MODULE_ALIAS("platform:jz4740-ohci");
index fb947655badd02de231dd0777e88499c8a552044..9c4143112e6c6d0f68961bb3f035ecbdefde07ba 100644 (file)
@@ -1475,6 +1475,32 @@ config MT7621_WDT
        help
          Hardware driver for the Mediatek/Ralink MT7621/8 SoC Watchdog Timer.
 
+config PIC32_WDT
+       tristate "Microchip PIC32 hardware watchdog"
+       select WATCHDOG_CORE
+       depends on MACH_PIC32
+       help
+         Watchdog driver for the built in watchdog hardware in a PIC32.
+
+         Configuration bits must be set appropriately for the watchdog to be
+         controlled by this driver.
+
+         To compile this driver as a loadable module, choose M here.
+         The module will be called pic32-wdt.
+
+config PIC32_DMT
+       tristate "Microchip PIC32 Deadman Timer"
+       select WATCHDOG_CORE
+       depends on MACH_PIC32
+       help
+         Watchdog driver for PIC32 instruction fetch counting timer. This specific
+         timer is typically be used in misson critical and safety critical
+         applications, where any single failure of the software functionality
+         and sequencing must be detected.
+
+         To compile this driver as a loadable module, choose M here.
+         The module will be called pic32-dmt.
+
 # PARISC Architecture
 
 # POWERPC Architecture
index feb6270fdbde5f4d19eb133f52d706e34b6b06f9..9bde095ff691b0ebe5f98201084b81cedf81da77 100644 (file)
@@ -157,6 +157,8 @@ obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
+obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
+obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
 
 # PARISC Architecture
 
diff --git a/drivers/watchdog/pic32-dmt.c b/drivers/watchdog/pic32-dmt.c
new file mode 100644 (file)
index 0000000..962f58c
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * PIC32 deadman timer driver
+ *
+ * Purna Chandra Mandal <purna.mandal@microchip.com>
+ * Copyright (c) 2016, Microchip Technology Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/watchdog.h>
+
+#include <asm/mach-pic32/pic32.h>
+
+/* Deadman Timer Regs */
+#define DMTCON_REG     0x00
+#define DMTPRECLR_REG  0x10
+#define DMTCLR_REG     0x20
+#define DMTSTAT_REG    0x30
+#define DMTCNT_REG     0x40
+#define DMTPSCNT_REG   0x60
+#define DMTPSINTV_REG  0x70
+
+/* Deadman Timer Regs fields */
+#define DMT_ON                 BIT(15)
+#define DMT_STEP1_KEY          BIT(6)
+#define DMT_STEP2_KEY          BIT(3)
+#define DMTSTAT_WINOPN         BIT(0)
+#define DMTSTAT_EVENT          BIT(5)
+#define DMTSTAT_BAD2           BIT(6)
+#define DMTSTAT_BAD1           BIT(7)
+
+/* Reset Control Register fields for watchdog */
+#define RESETCON_DMT_TIMEOUT   BIT(5)
+
+struct pic32_dmt {
+       void __iomem    *regs;
+       struct clk      *clk;
+};
+
+static inline void dmt_enable(struct pic32_dmt *dmt)
+{
+       writel(DMT_ON, PIC32_SET(dmt->regs + DMTCON_REG));
+}
+
+static inline void dmt_disable(struct pic32_dmt *dmt)
+{
+       writel(DMT_ON, PIC32_CLR(dmt->regs + DMTCON_REG));
+       /*
+        * Cannot touch registers in the CPU cycle following clearing the
+        * ON bit.
+        */
+       nop();
+}
+
+static inline int dmt_bad_status(struct pic32_dmt *dmt)
+{
+       u32 val;
+
+       val = readl(dmt->regs + DMTSTAT_REG);
+       val &= (DMTSTAT_BAD1 | DMTSTAT_BAD2 | DMTSTAT_EVENT);
+       if (val)
+               return -EAGAIN;
+
+       return 0;
+}
+
+static inline int dmt_keepalive(struct pic32_dmt *dmt)
+{
+       u32 v;
+       u32 timeout = 500;
+
+       /* set pre-clear key */
+       writel(DMT_STEP1_KEY << 8, dmt->regs + DMTPRECLR_REG);
+
+       /* wait for DMT window to open */
+       while (--timeout) {
+               v = readl(dmt->regs + DMTSTAT_REG) & DMTSTAT_WINOPN;
+               if (v == DMTSTAT_WINOPN)
+                       break;
+       }
+
+       /* apply key2 */
+       writel(DMT_STEP2_KEY, dmt->regs + DMTCLR_REG);
+
+       /* check whether keys are latched correctly */
+       return dmt_bad_status(dmt);
+}
+
+static inline u32 pic32_dmt_get_timeout_secs(struct pic32_dmt *dmt)
+{
+       unsigned long rate;
+
+       rate = clk_get_rate(dmt->clk);
+       if (rate)
+               return readl(dmt->regs + DMTPSCNT_REG) / rate;
+
+       return 0;
+}
+
+static inline u32 pic32_dmt_bootstatus(struct pic32_dmt *dmt)
+{
+       u32 v;
+       void __iomem *rst_base;
+
+       rst_base = ioremap(PIC32_BASE_RESET, 0x10);
+       if (!rst_base)
+               return 0;
+
+       v = readl(rst_base);
+
+       writel(RESETCON_DMT_TIMEOUT, PIC32_CLR(rst_base));
+
+       iounmap(rst_base);
+       return v & RESETCON_DMT_TIMEOUT;
+}
+
+static int pic32_dmt_start(struct watchdog_device *wdd)
+{
+       struct pic32_dmt *dmt = watchdog_get_drvdata(wdd);
+
+       dmt_enable(dmt);
+       return dmt_keepalive(dmt);
+}
+
+static int pic32_dmt_stop(struct watchdog_device *wdd)
+{
+       struct pic32_dmt *dmt = watchdog_get_drvdata(wdd);
+
+       dmt_disable(dmt);
+
+       return 0;
+}
+
+static int pic32_dmt_ping(struct watchdog_device *wdd)
+{
+       struct pic32_dmt *dmt = watchdog_get_drvdata(wdd);
+
+       return dmt_keepalive(dmt);
+}
+
+static const struct watchdog_ops pic32_dmt_fops = {
+       .owner          = THIS_MODULE,
+       .start          = pic32_dmt_start,
+       .stop           = pic32_dmt_stop,
+       .ping           = pic32_dmt_ping,
+};
+
+static const struct watchdog_info pic32_dmt_ident = {
+       .options        = WDIOF_KEEPALIVEPING |
+                         WDIOF_MAGICCLOSE,
+       .identity       = "PIC32 Deadman Timer",
+};
+
+static struct watchdog_device pic32_dmt_wdd = {
+       .info           = &pic32_dmt_ident,
+       .ops            = &pic32_dmt_fops,
+};
+
+static int pic32_dmt_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct pic32_dmt *dmt;
+       struct resource *mem;
+       struct watchdog_device *wdd = &pic32_dmt_wdd;
+
+       dmt = devm_kzalloc(&pdev->dev, sizeof(*dmt), GFP_KERNEL);
+       if (IS_ERR(dmt))
+               return PTR_ERR(dmt);
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       dmt->regs = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(dmt->regs))
+               return PTR_ERR(dmt->regs);
+
+       dmt->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dmt->clk)) {
+               dev_err(&pdev->dev, "clk not found\n");
+               return PTR_ERR(dmt->clk);
+       }
+
+       ret = clk_prepare_enable(dmt->clk);
+       if (ret)
+               return ret;
+
+       wdd->timeout = pic32_dmt_get_timeout_secs(dmt);
+       if (!wdd->timeout) {
+               dev_err(&pdev->dev,
+                       "failed to read watchdog register timeout\n");
+               ret = -EINVAL;
+               goto out_disable_clk;
+       }
+
+       dev_info(&pdev->dev, "timeout %d\n", wdd->timeout);
+
+       wdd->bootstatus = pic32_dmt_bootstatus(dmt) ? WDIOF_CARDRESET : 0;
+
+       watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT);
+       watchdog_set_drvdata(wdd, dmt);
+
+       ret = watchdog_register_device(wdd);
+       if (ret) {
+               dev_err(&pdev->dev, "watchdog register failed, err %d\n", ret);
+               goto out_disable_clk;
+       }
+
+       platform_set_drvdata(pdev, wdd);
+       return 0;
+
+out_disable_clk:
+       clk_disable_unprepare(dmt->clk);
+       return ret;
+}
+
+static int pic32_dmt_remove(struct platform_device *pdev)
+{
+       struct watchdog_device *wdd = platform_get_drvdata(pdev);
+       struct pic32_dmt *dmt = watchdog_get_drvdata(wdd);
+
+       watchdog_unregister_device(wdd);
+       clk_disable_unprepare(dmt->clk);
+
+       return 0;
+}
+
+static const struct of_device_id pic32_dmt_of_ids[] = {
+       { .compatible = "microchip,pic32mzda-dmt",},
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pic32_dmt_of_ids);
+
+static struct platform_driver pic32_dmt_driver = {
+       .probe          = pic32_dmt_probe,
+       .remove         = pic32_dmt_remove,
+       .driver         = {
+               .name           = "pic32-dmt",
+               .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(pic32_dmt_of_ids),
+       }
+};
+
+module_platform_driver(pic32_dmt_driver);
+
+MODULE_AUTHOR("Purna Chandra Mandal <purna.mandal@microchip.com>");
+MODULE_DESCRIPTION("Microchip PIC32 DMT Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/pic32-wdt.c b/drivers/watchdog/pic32-wdt.c
new file mode 100644 (file)
index 0000000..6047aa8
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * PIC32 watchdog driver
+ *
+ * Joshua Henderson <joshua.henderson@microchip.com>
+ * Copyright (c) 2016, Microchip Technology Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/watchdog.h>
+
+#include <asm/mach-pic32/pic32.h>
+
+/* Watchdog Timer Registers */
+#define WDTCON_REG             0x00
+
+/* Watchdog Timer Control Register fields */
+#define WDTCON_WIN_EN          BIT(0)
+#define WDTCON_RMCS_MASK       0x0003
+#define WDTCON_RMCS_SHIFT      0x0006
+#define WDTCON_RMPS_MASK       0x001F
+#define WDTCON_RMPS_SHIFT      0x0008
+#define WDTCON_ON              BIT(15)
+#define WDTCON_CLR_KEY         0x5743
+
+/* Reset Control Register fields for watchdog */
+#define RESETCON_TIMEOUT_IDLE  BIT(2)
+#define RESETCON_TIMEOUT_SLEEP BIT(3)
+#define RESETCON_WDT_TIMEOUT   BIT(4)
+
+struct pic32_wdt {
+       void __iomem    *regs;
+       void __iomem    *rst_base;
+       struct clk      *clk;
+};
+
+static inline bool pic32_wdt_is_win_enabled(struct pic32_wdt *wdt)
+{
+       return !!(readl(wdt->regs + WDTCON_REG) & WDTCON_WIN_EN);
+}
+
+static inline u32 pic32_wdt_get_post_scaler(struct pic32_wdt *wdt)
+{
+       u32 v = readl(wdt->regs + WDTCON_REG);
+
+       return (v >> WDTCON_RMPS_SHIFT) & WDTCON_RMPS_MASK;
+}
+
+static inline u32 pic32_wdt_get_clk_id(struct pic32_wdt *wdt)
+{
+       u32 v = readl(wdt->regs + WDTCON_REG);
+
+       return (v >> WDTCON_RMCS_SHIFT) & WDTCON_RMCS_MASK;
+}
+
+static int pic32_wdt_bootstatus(struct pic32_wdt *wdt)
+{
+       u32 v = readl(wdt->rst_base);
+
+       writel(RESETCON_WDT_TIMEOUT, PIC32_CLR(wdt->rst_base));
+
+       return v & RESETCON_WDT_TIMEOUT;
+}
+
+static u32 pic32_wdt_get_timeout_secs(struct pic32_wdt *wdt, struct device *dev)
+{
+       unsigned long rate;
+       u32 period, ps, terminal;
+
+       rate = clk_get_rate(wdt->clk);
+
+       dev_dbg(dev, "wdt: clk_id %d, clk_rate %lu (prescale)\n",
+               pic32_wdt_get_clk_id(wdt), rate);
+
+       /* default, prescaler of 32 (i.e. div-by-32) is implicit. */
+       rate >>= 5;
+       if (!rate)
+               return 0;
+
+       /* calculate terminal count from postscaler. */
+       ps = pic32_wdt_get_post_scaler(wdt);
+       terminal = BIT(ps);
+
+       /* find time taken (in secs) to reach terminal count */
+       period = terminal / rate;
+       dev_dbg(dev,
+               "wdt: clk_rate %lu (postscale) / terminal %d, timeout %dsec\n",
+               rate, terminal, period);
+
+       return period;
+}
+
+static void pic32_wdt_keepalive(struct pic32_wdt *wdt)
+{
+       /* write key through single half-word */
+       writew(WDTCON_CLR_KEY, wdt->regs + WDTCON_REG + 2);
+}
+
+static int pic32_wdt_start(struct watchdog_device *wdd)
+{
+       struct pic32_wdt *wdt = watchdog_get_drvdata(wdd);
+
+       writel(WDTCON_ON, PIC32_SET(wdt->regs + WDTCON_REG));
+       pic32_wdt_keepalive(wdt);
+
+       return 0;
+}
+
+static int pic32_wdt_stop(struct watchdog_device *wdd)
+{
+       struct pic32_wdt *wdt = watchdog_get_drvdata(wdd);
+
+       writel(WDTCON_ON, PIC32_CLR(wdt->regs + WDTCON_REG));
+
+       /*
+        * Cannot touch registers in the CPU cycle following clearing the
+        * ON bit.
+        */
+       nop();
+
+       return 0;
+}
+
+static int pic32_wdt_ping(struct watchdog_device *wdd)
+{
+       struct pic32_wdt *wdt = watchdog_get_drvdata(wdd);
+
+       pic32_wdt_keepalive(wdt);
+
+       return 0;
+}
+
+static const struct watchdog_ops pic32_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .start          = pic32_wdt_start,
+       .stop           = pic32_wdt_stop,
+       .ping           = pic32_wdt_ping,
+};
+
+static const struct watchdog_info pic32_wdt_ident = {
+       .options = WDIOF_KEEPALIVEPING |
+                       WDIOF_MAGICCLOSE | WDIOF_CARDRESET,
+       .identity = "PIC32 Watchdog",
+};
+
+static struct watchdog_device pic32_wdd = {
+       .info           = &pic32_wdt_ident,
+       .ops            = &pic32_wdt_fops,
+};
+
+static const struct of_device_id pic32_wdt_dt_ids[] = {
+       { .compatible = "microchip,pic32mzda-wdt", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pic32_wdt_dt_ids);
+
+static int pic32_wdt_drv_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct watchdog_device *wdd = &pic32_wdd;
+       struct pic32_wdt *wdt;
+       struct resource *mem;
+
+       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+       if (IS_ERR(wdt))
+               return PTR_ERR(wdt);
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       wdt->regs = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(wdt->regs))
+               return PTR_ERR(wdt->regs);
+
+       wdt->rst_base = devm_ioremap(&pdev->dev, PIC32_BASE_RESET, 0x10);
+       if (IS_ERR(wdt->rst_base))
+               return PTR_ERR(wdt->rst_base);
+
+       wdt->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(wdt->clk)) {
+               dev_err(&pdev->dev, "clk not found\n");
+               return PTR_ERR(wdt->clk);
+       }
+
+       ret = clk_prepare_enable(wdt->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "clk enable failed\n");
+               return ret;
+       }
+
+       if (pic32_wdt_is_win_enabled(wdt)) {
+               dev_err(&pdev->dev, "windowed-clear mode is not supported.\n");
+               ret = -ENODEV;
+               goto out_disable_clk;
+       }
+
+       wdd->timeout = pic32_wdt_get_timeout_secs(wdt, &pdev->dev);
+       if (!wdd->timeout) {
+               dev_err(&pdev->dev,
+                       "failed to read watchdog register timeout\n");
+               ret = -EINVAL;
+               goto out_disable_clk;
+       }
+
+       dev_info(&pdev->dev, "timeout %d\n", wdd->timeout);
+
+       wdd->bootstatus = pic32_wdt_bootstatus(wdt) ? WDIOF_CARDRESET : 0;
+
+       watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT);
+       watchdog_set_drvdata(wdd, wdt);
+
+       ret = watchdog_register_device(wdd);
+       if (ret) {
+               dev_err(&pdev->dev, "watchdog register failed, err %d\n", ret);
+               goto out_disable_clk;
+       }
+
+       platform_set_drvdata(pdev, wdd);
+
+       return 0;
+
+out_disable_clk:
+       clk_disable_unprepare(wdt->clk);
+
+       return ret;
+}
+
+static int pic32_wdt_drv_remove(struct platform_device *pdev)
+{
+       struct watchdog_device *wdd = platform_get_drvdata(pdev);
+       struct pic32_wdt *wdt = watchdog_get_drvdata(wdd);
+
+       watchdog_unregister_device(wdd);
+       clk_disable_unprepare(wdt->clk);
+
+       return 0;
+}
+
+static struct platform_driver pic32_wdt_driver = {
+       .probe          = pic32_wdt_drv_probe,
+       .remove         = pic32_wdt_drv_remove,
+       .driver         = {
+               .name           = "pic32-wdt",
+               .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(pic32_wdt_dt_ids),
+       }
+};
+
+module_platform_driver(pic32_wdt_driver);
+
+MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>");
+MODULE_DESCRIPTION("Microchip PIC32 Watchdog Timer");
+MODULE_LICENSE("GPL");
index 8afe10cf7df80f042ec1c3a34b3c3d412f5a3fce..8ab782d8b33ddc7f4ac9e2fec72230ca0d4a060b 100644 (file)
@@ -1071,7 +1071,7 @@ static int __init parse_crash_elf32_headers(void)
        /* Do some basic Verification. */
        if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
                (ehdr.e_type != ET_CORE) ||
-               !elf_check_arch(&ehdr) ||
+               !vmcore_elf32_check_arch(&ehdr) ||
                ehdr.e_ident[EI_CLASS] != ELFCLASS32||
                ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
                ehdr.e_version != EV_CURRENT ||
index c9ccafa0d99a30819e91f582892c775f4c59ed3b..e74072d23e692b0a1c6bfd6c5b63b08a396e17c0 100644 (file)
 #define __NR_seccomp_sigreturn         __NR_rt_sigreturn
 #endif
 
+#ifdef CONFIG_COMPAT
+#ifndef get_compat_mode1_syscalls
+static inline const int *get_compat_mode1_syscalls(void)
+{
+       static const int mode1_syscalls_32[] = {
+               __NR_seccomp_read_32, __NR_seccomp_write_32,
+               __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
+               0, /* null terminated */
+       };
+       return mode1_syscalls_32;
+}
+#endif
+#endif /* CONFIG_COMPAT */
+
 #endif /* _ASM_GENERIC_SECCOMP_H */
index 3d1a3af5cf595ccc4e2c9fc5f0060edca1d96272..a2508a8f9a9ce266677a3176d74d56ee10ae5129 100644 (file)
 struct siginfo;
 void do_schedule_next_timer(struct siginfo *info);
 
-#ifndef HAVE_ARCH_COPY_SIGINFO
-
-#include <linux/string.h>
-
-static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
-{
-       if (from->si_code < 0)
-               memcpy(to, from, sizeof(*to));
-       else
-               /* _sigchld is currently the largest know union member */
-               memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
-}
-
-#endif
-
 extern int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from);
 
 #endif
diff --git a/include/dt-bindings/clock/ath79-clk.h b/include/dt-bindings/clock/ath79-clk.h
new file mode 100644 (file)
index 0000000..27359ad
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014, 2016 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * 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 __DT_BINDINGS_ATH79_CLK_H
+#define __DT_BINDINGS_ATH79_CLK_H
+
+#define ATH79_CLK_CPU          0
+#define ATH79_CLK_DDR          1
+#define ATH79_CLK_AHB          2
+
+#define ATH79_CLK_END          3
+
+#endif /* __DT_BINDINGS_ATH79_CLK_H */
diff --git a/include/dt-bindings/clock/microchip,pic32-clock.h b/include/dt-bindings/clock/microchip,pic32-clock.h
new file mode 100644 (file)
index 0000000..184647a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Purna Chandra Mandal,<purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology 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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MICROCHIP_PIC32_H_
+#define _DT_BINDINGS_CLK_MICROCHIP_PIC32_H_
+
+/* clock output indices */
+#define POSCCLK                0
+#define FRCCLK         1
+#define BFRCCLK                2
+#define LPRCCLK                3
+#define SOSCCLK                4
+#define FRCDIVCLK      5
+#define PLLCLK         6
+#define SCLK           7
+#define PB1CLK         8
+#define PB2CLK         9
+#define PB3CLK         10
+#define PB4CLK         11
+#define PB5CLK         12
+#define PB6CLK         13
+#define PB7CLK         14
+#define REF1CLK                15
+#define REF2CLK                16
+#define REF3CLK                17
+#define REF4CLK                18
+#define REF5CLK                19
+#define UPLLCLK                20
+#define MAXCLKS                21
+
+#endif /* _DT_BINDINGS_CLK_MICROCHIP_PIC32_H_ */
diff --git a/include/linux/bcm47xx_sprom.h b/include/linux/bcm47xx_sprom.h
new file mode 100644 (file)
index 0000000..c06b47c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __BCM47XX_SPROM_H
+#define __BCM47XX_SPROM_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+
+#ifdef CONFIG_BCM47XX_SPROM
+int bcm47xx_sprom_register_fallbacks(void);
+#else
+static inline int bcm47xx_sprom_register_fallbacks(void)
+{
+       return -ENOTSUPP;
+};
+#endif
+
+#endif /* __BCM47XX_SPROM_H */
index 3849fce7ecfe6df067f365d44bd8951c87cd0184..3873697ba21c88510fb55b061fa167bdc4b47581 100644 (file)
@@ -34,9 +34,13 @@ void vmcore_cleanup(void);
 
 /*
  * Architecture code can redefine this if there are any special checks
- * needed for 64-bit ELF vmcores. In case of 32-bit only architecture,
- * this can be set to zero.
+ * needed for 32-bit ELF or 64-bit ELF vmcores.  In case of 32-bit
+ * only architecture, vmcore_elf64_check_arch can be set to zero.
  */
+#ifndef vmcore_elf32_check_arch
+#define vmcore_elf32_check_arch(x) elf_check_arch(x)
+#endif
+
 #ifndef vmcore_elf64_check_arch
 #define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
 #endif
index 80f89e4a29ac5d714a4cd8e239b408367edd9d37..81f930b0bca97daf7a05ca5b94c70f77a4fd3b2a 100644 (file)
 #define GIC_VPE_SWINT0_MAP_OFS         0x0054
 #define GIC_VPE_SWINT1_MAP_OFS         0x0058
 #define GIC_VPE_OTHER_ADDR_OFS         0x0080
+#define GIC_VP_IDENT_OFS               0x0088
 #define GIC_VPE_WD_CONFIG0_OFS         0x0090
 #define GIC_VPE_WD_COUNT0_OFS          0x0094
 #define GIC_VPE_WD_INITIAL0_OFS                0x0098
 #define GIC_VPE_SMASK_FDC_SHF          6
 #define GIC_VPE_SMASK_FDC_MSK          (MSK(1) << GIC_VPE_SMASK_FDC_SHF)
 
+/* GIC_VP_IDENT fields */
+#define GIC_VP_IDENT_VCNUM_SHF         0
+#define GIC_VP_IDENT_VCNUM_MSK         (MSK(6) << GIC_VP_IDENT_VCNUM_SHF)
+
 /* GIC nomenclature for Core Interrupt Pins. */
 #define GIC_CPU_INT0           0 /* Core Interrupt 2 */
 #define GIC_CPU_INT1           1 /* .                */
@@ -278,4 +283,16 @@ static inline int gic_get_usm_range(struct resource *gic_usm_res)
 
 #endif /* CONFIG_MIPS_GIC */
 
+/**
+ * gic_read_local_vp_id() - read the local VPs VCNUM
+ *
+ * Read the VCNUM of the local VP from the GIC_VP_IDENT register and
+ * return it to the caller. This ID should be used to refer to the VP
+ * via the GICs VP-other region, or when calculating an offset to a
+ * bit representing the VP in interrupt masks.
+ *
+ * Return: The VCNUM value for the local VP.
+ */
+extern unsigned gic_read_local_vp_id(void);
+
 #endif /* __LINUX_IRQCHIP_MIPS_GIC_H */
index 3fbe81444d31e85db8b1bb0bb517a7d5ae4b5860..639be264f5f97a257b6887d4d8dbe82ce510aa7e 100644 (file)
@@ -28,6 +28,21 @@ struct sigpending {
        sigset_t signal;
 };
 
+#ifndef HAVE_ARCH_COPY_SIGINFO
+
+#include <linux/string.h>
+
+static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
+{
+       if (from->si_code < 0)
+               memcpy(to, from, sizeof(*to));
+       else
+               /* _sigchld is currently the largest know union member */
+               memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
+}
+
+#endif
+
 /*
  * Define some primitives to manipulate sigset_t.
  */
index e513a4ee369bb31a9bf0ce4c28917ca2ea204edc..24da334af7f1933fb69c0566d18e73a23d95ef75 100644 (file)
 /* MVEBU UART */
 #define PORT_MVEBU     114
 
+/* Microchip PIC32 UART */
+#define PORT_PIC32     115
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
index 6c9bb62ed0466ac1b387c051cd3e1fdfec3335d6..7002796f14a493988f6da70f77e266e36bf7788d 100644 (file)
@@ -513,24 +513,17 @@ static void seccomp_send_sigsys(int syscall, int reason)
  * To be fully secure this must be combined with rlimit
  * to limit the stack allocations too.
  */
-static int mode1_syscalls[] = {
+static const int mode1_syscalls[] = {
        __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn,
        0, /* null terminated */
 };
 
-#ifdef CONFIG_COMPAT
-static int mode1_syscalls_32[] = {
-       __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
-       0, /* null terminated */
-};
-#endif
-
 static void __secure_computing_strict(int this_syscall)
 {
-       int *syscall_whitelist = mode1_syscalls;
+       const int *syscall_whitelist = mode1_syscalls;
 #ifdef CONFIG_COMPAT
        if (in_compat_syscall())
-               syscall_whitelist = mode1_syscalls_32;
+               syscall_whitelist = get_compat_mode1_syscalls();
 #endif
        do {
                if (*syscall_whitelist == this_syscall)
index 7bfe9fa1c8dc6db8d6c4415fbf0d26e66477e42e..d135882e2c40936753c0dc7ffb0362d95532d2c3 100755 (executable)
@@ -5,6 +5,6 @@
        gsub(".*version ", "");
        gsub("-.*", "");
        split($1,a, ".");
-       print a[1]*100000000 + a[2]*1000000 + a[3]*10000 + a[4]*100 + a[5];
+       print a[1]*100000000 + a[2]*1000000 + a[3]*10000;
        exit
        }
index 150829dd799876dc11a64bddff1760efb4a13066..7947e568e0576905265e58a19caf6886633acaac 100644 (file)
@@ -5,6 +5,7 @@
  * Test code for seccomp bpf.
  */
 
+#include <sys/types.h>
 #include <asm/siginfo.h>
 #define __have_siginfo_t 1
 #define __have_sigval_t 1
@@ -14,7 +15,6 @@
 #include <linux/filter.h>
 #include <sys/prctl.h>
 #include <sys/ptrace.h>
-#include <sys/types.h>
 #include <sys/user.h>
 #include <linux/prctl.h>
 #include <linux/ptrace.h>
@@ -1242,6 +1242,12 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 # define ARCH_REGS     s390_regs
 # define SYSCALL_NUM   gprs[2]
 # define SYSCALL_RET   gprs[2]
+#elif defined(__mips__)
+# define ARCH_REGS     struct pt_regs
+# define SYSCALL_NUM   regs[2]
+# define SYSCALL_SYSCALL_NUM regs[4]
+# define SYSCALL_RET   regs[2]
+# define SYSCALL_NUM_RET_SHARE_REG
 #else
 # error "Do not know how to find your architecture's registers and syscalls"
 #endif
@@ -1249,7 +1255,7 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 /* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
  * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
  */
-#if defined(__x86_64__) || defined(__i386__)
+#if defined(__x86_64__) || defined(__i386__) || defined(__mips__)
 #define HAVE_GETREGS
 #endif
 
@@ -1273,6 +1279,10 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
        }
 #endif
 
+#if defined(__mips__)
+       if (regs.SYSCALL_NUM == __NR_O32_Linux)
+               return regs.SYSCALL_SYSCALL_NUM;
+#endif
        return regs.SYSCALL_NUM;
 }
 
@@ -1297,6 +1307,13 @@ void change_syscall(struct __test_metadata *_metadata,
        {
                regs.SYSCALL_NUM = syscall;
        }
+#elif defined(__mips__)
+       {
+               if (regs.SYSCALL_NUM == __NR_O32_Linux)
+                       regs.SYSCALL_SYSCALL_NUM = syscall;
+               else
+                       regs.SYSCALL_NUM = syscall;
+       }
 
 #elif defined(__arm__)
 # ifndef PTRACE_SET_SYSCALL
@@ -1327,7 +1344,11 @@ void change_syscall(struct __test_metadata *_metadata,
 
        /* If syscall is skipped, change return value. */
        if (syscall == -1)
+#ifdef SYSCALL_NUM_RET_SHARE_REG
+               TH_LOG("Can't modify syscall return on this architecture");
+#else
                regs.SYSCALL_RET = 1;
+#endif
 
 #ifdef HAVE_GETREGS
        ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs);
@@ -1465,8 +1486,13 @@ TEST_F(TRACE_syscall, syscall_dropped)
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
        ASSERT_EQ(0, ret);
 
+#ifdef SYSCALL_NUM_RET_SHARE_REG
+       /* gettid has been skipped */
+       EXPECT_EQ(-1, syscall(__NR_gettid));
+#else
        /* gettid has been skipped and an altered return value stored. */
        EXPECT_EQ(1, syscall(__NR_gettid));
+#endif
        EXPECT_NE(self->mytid, syscall(__NR_gettid));
 }